本文介绍了Java:为鼠标事件定义单位组件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要一个名为mainPanelJPanel并在上面添加几个组件;我还定义了一个mouseAdapter并添加到我的mainPanel中,它覆盖了mouseEnteredmouseExited以例如在鼠标输入时更改mainPanel的背景色.但是,当鼠标进入mainPanel并进入我在其上添加的组件(例如标签)时,将调用mouseExited事件.但是我不希望这样,因为鼠标位于mainPanel区域中.我希望它在鼠标退出mainPanel区域时被调用;并且也想要mouseEntered.我以前在mainPanel上的组件中添加了mouseListeners,但这不是一个明确的解决方案.谁能告诉我一个清晰的方法来达到我的目的?

I want to have a JPanel called mainPanel and add several components on it; Also I defined a mouseAdapter and added to my mainPanel that overrides mouseEntered and mouseExited to for example change background color of mainPanel when mouse entered it. But when mouse entered to mainPanel and entered to components I added on it (for example labels) mouseExited event is called; But I don't want this as mouse is in area of mainPanel; I want it be called just when mouse exited mainPanel area; and also want this for mouseEntered. I previously added mouseListeners to components on mainPanel but it is not a clear solution. Can anyone tell me a clear way for my purpose?

感谢您的关注;好锁

推荐答案

您希望在完全边界上调用mouseEnteredmouseExited.如您所注意到的,这对于正常" MouseListener是不可能直接实现的.

You want the mouseEntered and mouseExited to be called on full boundaries. This is, as you have noticed, not directly possible with the "normal" MouseListener.

最简单的方法是将侦听器添加到面板的所有子组件中:

The simplest way is to add the listener to all child-components of the panel:

private static void addListenerToAllComponents(JComponent c, MouseListener l) {

    c.addMouseListener(l);

    for (Component cc : c.getComponents())
        if (cc instanceof JComponent)
            addListenerToAllComponents((JComponent) cc, l);
}

完整示例:

public static void main(String[] args) {

    final JFrame frame = new JFrame("Test");

    frame.add(new JLabel("Testing"), BorderLayout.NORTH);

    final JPanel panel = new JPanel(new GridLayout(2, 1));
    panel.setBackground(Color.RED);

    MouseListener l = new MouseAdapter() {
        @Override
        public void mouseEntered(MouseEvent e) {
            panel.setBackground(Color.BLUE);
        }
        @Override
        public void mouseExited(MouseEvent e) {
            panel.setBackground(Color.RED);
        }
    };

    panel.add(new JLabel("Hello"));
    panel.add(new JTextField("World!"));

    addListenerToAllComponents(panel, l);

    frame.add(panel, BorderLayout.CENTER);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 300);
    frame.setVisible(true);
}


另一个解决方法(先前的答案)...

...用于设置 GlassPane 然后自己检查范围:


Another workaround (previous answer)...

...is to set a GlassPane and check bounds yourself:

public static void main(String[] args) {

    JFrame frame = new JFrame("Test");

    frame.add(new JLabel("Testing"), BorderLayout.NORTH);

    final JPanel panel = new JPanel(new GridLayout(2, 1));
    frame.add(panel, BorderLayout.CENTER);

    panel.add(new JLabel("Hello"));
    panel.add(new JTextField("World!"));

    class GlassPane extends JComponent {
        GlassPane(final JComponent c) {
            addMouseMotionListener(new MouseMotionAdapter() {
                @Override
                public void mouseMoved(MouseEvent e) {

                    Point p = SwingUtilities.convertPoint(e.getComponent(), 
                                                          e.getPoint(), 
                                                          c);

                    if (c.contains(p))
                        c.setBackground(Color.BLUE);
                    else
                        c.setBackground(Color.RED);
                }
            });

            addMouseListener(new MouseAdapter() {
                public void mouseExited(MouseEvent e) {
                    c.setBackground(Color.MAGENTA);
                }
            });
        }
    }        

    GlassPane glass = new GlassPane(panel);
    frame.setGlassPane(glass);
    glass.setVisible(true);

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(400, 300);
    frame.setVisible(true);
}


您需要查看一些内容...事件重新分配是其中之一,在您的情况下可能是个问题.遵循此示例并实施玻璃窗格上的事件分发侦听器:


There are some stuff you need to look in to... Event redistribution is one and might be a problem in your case. Follow this example and implement an event distribution listener on the glass pane:

MouseInputListener i = new MouseInputListener() {

    private void redispatchMouseEvent(MouseEvent e) {

        Point glassPanePoint = e.getPoint();
        Container container = frame.getContentPane();

        Point containerPoint = SwingUtilities.convertPoint(
                GlassPane.this,
                glassPanePoint,
                container);

        Component component = 
            SwingUtilities.getDeepestComponentAt(
                    container,
                    containerPoint.x,
                    containerPoint.y);

        if (component != null) {

            Point componentPoint = SwingUtilities.convertPoint(
                    GlassPane.this,
                    glassPanePoint,
                    component);

            component.dispatchEvent(new MouseEvent(component,
                    e.getID(),
                    e.getWhen(),
                    e.getModifiers(),
                    componentPoint.x,
                    componentPoint.y,
                    e.getClickCount(),
                    e.isPopupTrigger()));
        }
    }

    public void mouseMoved(MouseEvent e) {
        redispatchMouseEvent(e);
    }
    public void mouseDragged(MouseEvent e) {
        redispatchMouseEvent(e);
    }
    public void mouseClicked(MouseEvent e) {
        redispatchMouseEvent(e);
    }
    public void mouseEntered(MouseEvent e) {
        redispatchMouseEvent(e);
    }
    public void mouseExited(MouseEvent e) {
        redispatchMouseEvent(e);
    }
    public void mousePressed(MouseEvent e) {
        redispatchMouseEvent(e);
    }
    public void mouseReleased(MouseEvent e) {
        redispatchMouseEvent(e);
    }
};

addMouseListener(i);
addMouseMotionListener(i);

这篇关于Java:为鼠标事件定义单位组件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 21:04