【问题标题】:Change/Display Cursor with Text更改/显示带有文本的光标
【发布时间】:2015-01-07 15:23:36
【问题描述】:

我目前正在尝试将我的JFrame 上显示的光标更改为一些文本,例如“请稍等,您的工作正在完成”,而某个buttonactionPerformed() 方法正在执行。到目前为止,我发现的唯一解决方案是将Cursor 更改为包含我想要的文本的Image。代码如下:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.geom.Ellipse2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import javax.imageio.ImageIO;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;

public class Hasikome extends JFrame{

static Cursor cursor;

private static final long serialVersionUID = 1L;

public static void main(String[] args) {

        final Hasikome hasi = new Hasikome();
        hasi.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        hasi.setSize(new Dimension(1200, 1200));
        hasi.setPreferredSize(new Dimension(500, 500));
        Toolkit kit = Toolkit.getDefaultToolkit();
        Dimension dim = kit.getBestCursorSize(16, 16);
        BufferedImage buffered = null;
        try {
            buffered = ImageIO.read(new File(Paths.get("").toAbsolutePath().toString() + "\\belge.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        java.awt.Shape circle = new Ellipse2D.Float(0, 0, dim.width - 1, dim.height - 1);
        Graphics2D g = buffered.createGraphics();
        g.setColor(Color.BLUE);
        g.draw(circle);
        g.setColor(Color.RED);
        hasi.add(new JButton(new AbstractAction() {

            private static final long serialVersionUID = 1L;

            @Override
            public void actionPerformed(ActionEvent e) {
                hasi.setCursor(cursor);
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e1) {
                    e1.printStackTrace();
                } finally {
                    hasi.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
                }
            }
        }), BorderLayout.NORTH);
        int centerX = (dim.width - 1) /2;
        int centerY = (dim.height - 1) / 2;
        g.drawLine(centerX, 0, centerX, dim.height - 1);
        g.drawLine(0, centerY, dim.height - 1, centerY);
        g.dispose();
        cursor = kit.createCustomCursor(buffered, new Point(centerX, centerY), "myCursor");
        hasi.pack();
        hasi.setVisible(true);
    }
}

这段代码的问题是Dimension dim = kit.getBestCursorSize(16, 16); 这行总是在Windows 上生成大小为32x32 的Cursor,它依赖于平台。我不能使用超过 32x32 的值,否则我会得到 cursor = kit.createCustomCursor(buffered, new Point(centerX, centerY), "myCursor"); 行的异常。而且因为我使用了相当长的文本 (250x16),所以我无法正确地将 text image 显示为 Cursor

此解决方案不是必需的,我想要完成的是在执行某些 ButtonactionPerformed() 方法时向用户显示文本为 Cursor。有什么办法可以做到这一点吗?提前致谢。

【问题讨论】:

    标签: java swing cursor


    【解决方案1】:

    查看Disabled Glass Pane 了解一种方法。

    如果允许您在使用“等待”光标时显示Glass Pane,并在半透明背景上绘制文本。

    【讨论】:

      【解决方案2】:

      除非您绝对必须使用“请稍候”文本,否则仅使用计算机的内置加载图标可能会更容易。如果你使用:

      hasi.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
      doProcessing();
      hasi.setCursor(Cursor.getDefaultCursor());
      

      应该有同样的效果。

      【讨论】:

      • 这是正确的想法,但您需要在 setCursor 函数周围使用 SwingUtilities.invokeLater,并确保在非 UI 线程中使用 doProcessing()
      • 如果选择是我的,我也会使用它。然而,这些要求引导我寻找上述问题的答案。毕竟这一切和我正在寻找的答案没有操作上的差异,而是视觉上的差异。
      【解决方案3】:

      是否要阻塞 UI 线程?

      无论如何,最好的办法可能是使用 JLayeredPane,在 JLayeredPane 的模态层上弹出一个 JLabel(您需要自己设置其大小),然后在完成工作后将其移除。

      【讨论】:

      • 有一个关于你的答案的例子,我为对这个主题感兴趣的人找到了here
      【解决方案4】:

      这不是答案,但也许可以做你想做的事:

      package com.stackoverflow.questions;
      
      import java.awt.Color;
      import java.awt.Cursor;
      import java.awt.FlowLayout;
      import java.awt.Graphics;
      import java.awt.Graphics2D;
      import java.awt.Point;
      import java.awt.RenderingHints;
      import java.awt.Toolkit;
      import java.awt.event.ActionEvent;
      import java.awt.event.MouseAdapter;
      import java.awt.event.MouseEvent;
      import java.awt.image.BufferedImage;
      import javax.swing.AbstractAction;
      import javax.swing.JButton;
      import javax.swing.JComponent;
      import javax.swing.JFrame;
      import javax.swing.SwingUtilities;
      import javax.swing.SwingWorker;
      
      /**
       * Just an idea for the Stackoverflow question http://stackoverflow.com/questions/27822671
       */
      public class SO27822671 extends JFrame {
      
        /**
         * The Glasspane on which we'll draw the "please wait..." thing.
         */
        private MyGlassPane myGlassPane;
      
        /**
         * Blank cursor to hide the cursor.
         */
        private final Cursor blankCursor;
      
        /**
         * Init.
         */
        public SO27822671() {
          setDefaultCloseOperation(EXIT_ON_CLOSE);
          setBounds(300, 300, 400, 400);
      
          myGlassPane = new MyGlassPane();
          setGlassPane(myGlassPane);
      
          getContentPane().setLayout(new FlowLayout());
          getContentPane().add(new JButton(new AbstractAction("Click Me!") {
      
            @Override
            public void actionPerformed(ActionEvent e) {
              doMyStuff();
            }
          }));
      
          // http://stackoverflow.com/a/1984117/3366578
          blankCursor = Toolkit.getDefaultToolkit().createCustomCursor(
              new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB), new Point(0, 0), "blank cursor");
        }
      
        /**
         * Do the heavy stuff.
         */
        private void doMyStuff() {
          // show our glasspane
          myGlassPane.setVisible(true);
      
          // save the current cursor
          final Cursor currentCursor = getCursor();
      
          // hide the cursor
          setCursor(blankCursor);
      
          new SwingWorker<Void, Void>() {
      
            @Override
            protected Void doInBackground() throws Exception {
              // hard work here
              Thread.sleep(2000);
              return null;
            }
      
            @Override
            protected void done() {
              try {
                get();
              }
              catch (Exception e) {
                // do your exception handling here
                e.printStackTrace();
              }
              finally {
                // hide our glasspane
                myGlassPane.setVisible(false);
      
                // restore the cursor
                setCursor(currentCursor);
              }
            }
          }.execute();
        }
      
        /**
         * This is our glasspane.
         */
        class MyGlassPane extends JComponent {
      
          /**
           * To save the mouse X position.
           */
          private int mouseXPosition;
      
          /**
           * To save the mouse Y position.
           */
          private int mouseYPosition;
      
          /**
           * The text to show.
           */
          private String text = "Please wait...";
      
          /**
           * Init.
           */
          public MyGlassPane() {
            // to get the cursor position
            MouseAdapter mouseAdapter = new MouseAdapter() {
      
              @Override
              public void mouseMoved(MouseEvent e) {
                computeMousePositionAndRepaint(e);
              }
      
              @Override
              public void mouseEntered(MouseEvent e) {
                computeMousePositionAndRepaint(e);
              }
            };
      
            addMouseMotionListener(mouseAdapter);
            addMouseListener(mouseAdapter);
          }
      
          /**
           * Compute the mouse position and invoke repaint on our glasspane.
           * @param e 
           */
          private void computeMousePositionAndRepaint(MouseEvent e) {
            mouseXPosition = e.getX();
            mouseYPosition = e.getY();
            repaint();
          }
      
          @Override
          protected void paintComponent(Graphics g) {
            // draw here what you want instead
            int textHeight = g.getFontMetrics().getHeight();
            int textWidth = g.getFontMetrics().stringWidth(text);
            int textDescent = g.getFontMetrics().getDescent();
      
            int x = mouseXPosition - textWidth / 2;
            int y = mouseYPosition - textHeight / 2;
      
            g.setColor(Color.white);
            g.fillRect(x - 4, y - 4, textWidth + 8, textHeight + 8);
      
            ((Graphics2D) g).setRenderingHint(
                RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g.setColor(Color.black);
            g.drawString(text, x, y + textHeight - textDescent);
          }
        }
      
        public static void main(String[] args) {
          SwingUtilities.invokeLater(new Runnable() {
      
            @Override
            public void run() {
              new SO27822671().setVisible(true);
            }
          });
        }
      }
      

      只是一个想法

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-01-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-07
        • 2018-05-03
        相关资源
        最近更新 更多