【问题标题】:Java repainting a component at mouse-over.Java 在鼠标悬停时重新绘制组件。
【发布时间】:2011-09-18 06:16:02
【问题描述】:

我正在尝试制作我的第一个正确定制的 GUI,但我在更改为组件绘制的图像时遇到了困难。基本上,对于我的exitButton(一个JMenu),我覆盖了paint方法,然后添加了一个鼠标侦听器,但我不确定如何在鼠标输入方法中的mouseListener界面中重新绘制图像,然后在鼠标退出方法中再次绘制图像。本质上,我正在寻找一种重新绘制图像的方法,但我不知道我能做什么。任何帮助将不胜感激。

这里是相关代码sn-p:

exitBtn = new JMenu(){
       @Override
       protected void paintComponent(Graphics g) {
        super.paintComponent(g);
           ImageIcon exitBtnImg = new ImageIcon("src/images/userInterface/exitBtn.gif");
           g.drawImage(exitBtnImg.getImage(), 0, 5, null);
      }
  };
  exitBtn.setOpaque(false);
  exitBtn.setEnabled(false);
  exitBtn.setPreferredSize(new Dimension(43, 18));
  exitBtn.addMouseListener(new MouseListener() {
        @Override
        public void mousePressed(MouseEvent me) {
        }
        @Override
        public void mouseClicked(MouseEvent me) {
            System.exit(0);
        }
        @Override
        public void mouseEntered(MouseEvent me) {
            //ImageIcon exitBtnImg = new ImageIcon("src/images/exitBtn_hover.gif"); //The ImageIcon for the Image I want to use
            System.out.println("mouse entered");

        }
        @Override
        public void mouseExited(MouseEvent me) {
            // ImageIcon exitBtnImg = new ImageIcon("src/images/exitBtn.gif"); 

System.out.println("鼠标退出"); // 原始图像的图像图标 } @覆盖 公共无效鼠标释放(鼠标事件我){ } });

【问题讨论】:

    标签: java swing user-interface mouselistener jmenu


    【解决方案1】:

    我正在尝试制作我的第一个正确定制的 GUI

    您应该从阅读 Swing 教程开始。我不太确定您要做什么,但您的方法肯定是错误的。

    您可以从How to Use Menus 开始,它展示了如何使用 ActionListener 来处理鼠标点击。鼠标点击通常在菜单项上处理,而不是在菜单上。您通常会有类似“文件”菜单的内容,其中包含“退出”菜单项。

    然后,我还将查看 JMenu API 的各种方法,这些方法允许您在鼠标悬停或选择菜单时更改图标。也许 setRolloverEnabled(), setRolloverIcon() 就是你要找的。​​p>

    如果您仍有问题,请发布 SSCCE 来说明问题。

    更新:

    正如 Hovercraft 所述,翻转支持不适用于菜单或菜单项。有两个问题。首先,这些组件使用不同的 MouseListener。侦听器不侦听 mouseEntered 和 mouseExited 事件。第二个问题是两个组件的UI都已经自定义了,自定义的Icon绘制代码没有考虑到按钮的滚动状态。

    添加 MouseListener 很简单。自定义 UI(这是正确的解决方案)以正确支持翻转更复杂。

    对于一个似乎可行的简单技巧,我只是更新 MouseListener 中的图标,而不是让 UI 确定要绘制哪个图标。我建议您忘记此要求并使用不会更改菜单和菜单项图标的普通 UI。使用以下内容需您自担风险:

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.*;
    
    public class ButtonRollover extends JFrame
    {
        Icon normal;
        Icon rollover;
        Icon selected;
    
        public ButtonRollover()
        {
            MouseListener ml = new RolloverButtonListener();
    
            normal = new ColorIcon(Color.GREEN, 10, 10);
            rollover = new ColorIcon(Color.RED, 10, 10);
            selected = new ColorIcon(Color.BLUE, 10, 10);
    
            setLayout( new FlowLayout() );
    
            JMenuBar menuBar = new JMenuBar();
            setJMenuBar( menuBar );
    
            JMenu menu = (JMenu)createButton(new JMenu(), "Menu");
            menu.addMouseListener( ml );
            menuBar.add( menu );
    
            JMenuItem menuItem = (JMenuItem)createButton(new JMenuItem(), "MenuItem");
            menuItem.addMouseListener( ml );
            menu.add( menuItem );
    
            JButton button = (JButton)createButton(new JButton(), "Button");
            add( button );
    
            JCheckBox checkBox = (JCheckBox)createButton(new JCheckBox(), "CheckBox");
            add( checkBox );
    
            JRadioButton radioButton = (JRadioButton)createButton(new JRadioButton(), "RadioButton");
            add( radioButton );
        }
    
    
        public AbstractButton createButton(AbstractButton button, String text)
        {
            button.setText( text );
            button.setIcon( normal );
            button.setSelectedIcon( selected );
            button.setRolloverIcon( rollover );
            button.setRolloverSelectedIcon( rollover );
    
            System.out.println( text );
            MouseListener[] mls = button.getMouseListeners();
    
            for (MouseListener ml: mls)
            {
                System.out.println( "\t" + ml);
            }
    
            return button;
        }
    
        class RolloverButtonListener extends MouseAdapter
        {
            private Icon normal;
    
            public void mouseEntered(MouseEvent e)
            {
                AbstractButton b = (AbstractButton) e.getSource();
                ButtonModel model = b.getModel();
    
                if (b.isRolloverEnabled() && !SwingUtilities.isLeftMouseButton(e))
                {
                    normal = b.getIcon();
                    b.setIcon(b.getRolloverIcon());
                    model.setRollover(true);
                }
            }
    
            public void mouseExited(MouseEvent e)
            {
                AbstractButton b = (AbstractButton) e.getSource();
                ButtonModel model = b.getModel();
    
                if(b.isRolloverEnabled())
                {
                    b.setIcon( normal );
                    model.setRollover(false);
                }
            };
    
        }
    
        public class ColorIcon implements Icon
        {
            private Color color;
            private int width;
            private int height;
    
            public ColorIcon(Color color, int width, int height)
            {
                this.color = color;
                this.width = width;
                this.height = height;
            }
    
            public int getIconWidth()
            {
                return width;
            }
    
            public int getIconHeight()
            {
                return height;
            }
    
            public void paintIcon(Component c, Graphics g, int x, int y)
            {
                g.setColor(color);
                g.fillRect(x, y, width, height);
            }
        }
    
        public static void main(String[] args)
        {
            try
            {
    //          UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            }
            catch (Exception e) { }
    
            ButtonRollover frame = new ButtonRollover();
            frame.setDefaultCloseOperation( EXIT_ON_CLOSE );
            frame.setSize(400, 200);
            frame.setLocationRelativeTo( null );
            frame.setVisible(true);
        }
    }
    

    【讨论】:

    • 对我来说太复杂了,+1 用于从 ComponentUI 中提取 MouseListener,使用 SwingUtilities..
    • 嗨,非常感谢你的帮助,我设法让你的方法奏效,但它产生了一些其他问题,例如在调整大小时它替换了所有按钮的图像,因为它难以隔离按住鼠标时的按钮。尽管如此,您的方法给了我创建自己的方法所需的想法。谢谢
    • 我认为在 JMenuItem 上,mouseentered 和 mouseexited 被监听。我刚刚测试过。
    【解决方案2】:

    RollOver 按钮适用于交换图标,但我无法让它适用于 JMenu:

    import java.awt.*;
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.net.URL;
    import javax.imageio.ImageIO;
    import javax.swing.*;
    
    public class SwapMenuIcons {
    
       private static final String KENAI_1 = "http://duke.kenai.com/iconSized/duke.gif";
       private static final String KENAI_2 = "http://duke.kenai.com/iconSized/penduke-transparent.gif";
    
       private static void createAndShowUI() {
          try {
             Image duke1 = ImageIO.read(new URL(KENAI_1));
             Image duke2 = ImageIO.read(new URL(KENAI_2));
             ImageIcon icon1 = new ImageIcon(duke1);
             ImageIcon icon2 = new ImageIcon(duke2);
    
             JMenu myMenu = new JMenu();
             myMenu.setIcon(icon1);
             myMenu.setRolloverIcon(icon2);
             myMenu.setRolloverEnabled(true);
    
             JButton myButton = new JButton(icon1);
             myButton.setRolloverIcon(icon2);
             JPanel btnPanel = new JPanel();
             btnPanel.add(myButton);
    
             JMenuBar menuBar = new JMenuBar();
             menuBar.add(myMenu);
    
             JFrame frame = new JFrame("SwapMenuIcons");
             frame.setJMenuBar(menuBar);
             frame.add(btnPanel, BorderLayout.CENTER);
             frame.setPreferredSize(new Dimension(400, 300));
             frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
             frame.pack();
             frame.setLocationRelativeTo(null);
             frame.setVisible(true);
          } catch (MalformedURLException e) {
             e.printStackTrace();
          } catch (IOException e) {
             e.printStackTrace();
          }
       }
    
       public static void main(String[] args) {
          java.awt.EventQueue.invokeLater(new Runnable() {
             public void run() {
                createAndShowUI();
             }
          });
       }
    }
    

    【讨论】:

    • 如果有记录就好了 :)。请参阅我的更新以获取 hack。
    • @camickr:很酷,感谢您的更新!我会投票给你,但我前一段时间已经这样做了,不能为同一个答案重复两次。
    【解决方案3】:

    许多不同的方式。最脏的方法是拥有一个全局布尔值 isMouseHovering,您可以使用 mouseEntered 和 mouseExited 在 true 和 false 之间切换。在这两个鼠标事件中,调用 repaint();在您的重绘方法中,根据该布尔值绘制图像。

    【讨论】:

    • -1,AbstractButton 组件中内置了翻转支持。不要重新发明轮子。
    • @camickr:但它不适用于 JMenu 对象,即使它们继承自 AbstractButton。为了证明这一点,将 ChangeListener 放在 JMenu 对象或其模型上,您将看不到对鼠标悬停的响应。
    • @Hovercraft Full Of Eels ChangeListener 和 Model +1
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    • 2021-12-03
    • 1970-01-01
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多