简体   繁体   English

Java在鼠标悬停时重新绘制组件。

[英]Java repainting a component at mouse-over.

I am attempting to make my first properly customised GUI, but I am having difficulty changing the image which has been painted for a component. 我正在尝试制作我的第一个正确定制的GUI,但是我很难更改为组件绘制的图像。 Basically, for my exitButton (a JMenu) I overwrite the paint method, and then add a Mouse listener, but I am not sure how to repaint the image within the mouseListener interface in the Mouse entered method and again in the mouse exited method. 基本上,对于我的exitButton(一个JMenu),我覆盖了paint方法,然后添加一个Mouse监听器,但我不知道如何在鼠标输入方法中重新绘制mouseListener接口内的图像,并再次在鼠标退出方法中重新绘制。 Essentially I am looking for a way to repaint the image, but I am lost as to what I can do. 基本上我正在寻找一种重新绘制图像的方法,但我迷失了我能做什么。 Any help would be greatly appreciated. 任何帮助将不胜感激。

Here is the relevant code snippet: 以下是相关的代码段:

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("mouse exited"); System.out.println(“鼠标退出”); // The imageicon for the origianl image } @Override public void mouseReleased(MouseEvent me) { } }); //原始图像的imageicon} @Override public void mouseReleased(MouseEvent me){}});

I am attempting to make my first properly customised GUI 我正在尝试制作我的第一个正确定制的GUI

You should start by reading the Swing tutorial. 您应该首先阅读Swing教程。 I'm not really sure what you are trying to do but your approach sure seems wrong. 我不确定你要做什么,但你的方法肯定是错的。

You can start with How to Use Menus which shows how to use an ActionListener to handle a mouse click. 您可以从如何使用菜单开始,该菜单显示如何使用ActionListener来处理鼠标单击。 Mouse clicks are generally handled on a menu item, not a menu. 鼠标点击通常在菜单项上处理,而不是菜单。 You would generally have something like a "File" menu that wouuld contain an "Exit" menu item. 您通常会有类似“文件”菜单的内容,其中包含“退出”菜单项。

Then I would also look at the JMenu API for various methods that allow you to change the Icon when you mouse over or select a menu. 然后我还会看一下JMenu API的各种方法,这些方法允许您在鼠标悬停或选择菜单时更改图标。 Maybe setRolloverEnabled(), setRolloverIcon() is what you are looking for. 也许setRolloverEnabled(),setRolloverIcon()就是你要找的。

If you still have problems, then post a SSCCE that demonstrates the problem. 如果您仍有问题,请发布一个证明问题的SSCCE

Update: 更新:

As mentioned by Hovercraft, rollover support does not work for menus or menu items. 如Hovercraft所述,翻转支持不适用于菜单或菜单项。 There are two problems. 有两个问题。 First of all a different MouseListener is used by these components. 首先,这些组件使用不同的MouseListener。 The listener does NOT listen for mouseEntered and mouseExited events. 监听器不监听mouseEntered和mouseExited事件。 The second problem is that the UI for the two components has been customized and the custom Icon painting code does not take into account the rollover state of the button. 第二个问题是两个组件的UI已经自定义,自定义图标绘制代码没有考虑按钮的翻转状态。

Adding a MouseListener is easy. 添加MouseListener很容易。 Customizing the UI (which is the proper solution) to properly support rollovers is more involved. 自定义UI(这是正确的解决方案)以更好地支持翻转更为复杂。

For a simple hack that seems to work, I just update the Icon in the MouseListener rather than having the UI determine which Icon to paint. 对于一个似乎有效的简单hack,我只是更新MouseListener中的Icon,而不是让UI确定要绘制哪个Icon。 I advise you to forget about this requirement and use a normal UI which does not change Icons for menus and menu items. 我建议你忘记这个要求并使用普通的UI,它不会改变菜单和菜单项的图标。 Use the following at your own risk: 使用以下风险需要您自担风险:

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);
    }
}

RollOver for a button works with swapping Icons, but I can't get it to work for a JMenu: RollOver for a button适用于交换图标,但我不能让它适用于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();
         }
      });
   }
}

Bunch of different ways. 一堆不同的方式。 The dirtiest would be to have a global boolean isMouseHovering that you flip between true and false with the mouseEntered and mouseExited. 最脏的是有一个全局布尔值isMouseHovering,你可以使用mouseEntered和mouseExited在true和false之间切换。 In both of these mouse events, call repaint(); 在这两个鼠标事件中,调用repaint(); In your repaint method, draw the image based on the value of that boolean. 在重绘方法中,根据该布尔值的值绘制图像。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM