如何避免在任何嵌套组件上触发 mouseExited

how to avoid mouseExited to fire while on any nested component

在我的代码中我有:

一个抽象 class 扩展 JComponent,其中包含一些 JTextFields。 JTextFields 不可编辑。 JComponent class 实现 MouseListener: - 当 mouseEntered 事件触发时,会添加一个边框。 - 当 mouseExited 事件触发时,边框被移除。 - 当 mouseClicked 事件触发时,该组件的所有字段都设置为可编辑。

这应该是这样工作的:

问题是: 当鼠标经过任何 JTextField 时,将触发 mouseExited。 你会如何解决这个问题?

接下来是一个简单的 class,它将向您展示一个 window,其中一个 jTextField 包含在一个面板中,该面板以与上述非常相似的方式实现 MouseListener。不要考虑它是如何写的,它只是为了目的!

public static void main(String[] args)  {       
        SwingUtilities.invokeLater(new Runnable() {
            public void run(){   
                int i=0;
                //mainWindow
                    JFrame mainWindow = new JFrame("MyFrame");
                    mainWindow.setLayout(new BorderLayout());
                    mainWindow.setMinimumSize(new Dimension(200,200));

                    JPanel viewPort = new JPanel();

                    final JTextField text = new JTextField("SOME_RANDOM_TEXT");
                    text.setEditable(false);

                    final JPanel panel = new JPanel();
                    panel.add(text);
                    panel.setBackground(Color.green);
                    panel.addMouseListener(new MouseListener() {
                        @Override
                        public void mouseReleased(MouseEvent e) {
                            //NOTHING
                        }
                        @Override
                        public void mousePressed(MouseEvent e) {
                            //NOTHING
                        }

                        @Override
                        public void mouseExited(MouseEvent e) {
                            panel.setBorder(BorderFactory.createEmptyBorder());
                        }

                        @Override
                        public void mouseEntered(MouseEvent e) {
                            panel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
                        }

                        @Override
                        public void mouseClicked(MouseEvent e) {
                            ((JTextField)panel.getComponent(0)).setEditable(true);
                            panel.getComponent(0).requestFocus();
                        }
                    });
                    viewPort.add(panel);
                    mainWindow.add(viewPort,BorderLayout.CENTER);
                    mainWindow.setVisible(true);
            }
        });
    }

问题是您将 MouseListener 设置为 JPanel,这没有多大意义(对于所需的描述行为)。

只需将 MouseListener 更改为 JTextField:

text.addMouseListener(new MouseListener() {

对我来说效果很好。


更新:

You missed something mate :) Thx for the fast answer, but, my JPanel can contains more then a single textField, it could contains for example, 10 of them!

这个例子可以作为例子,但在现实生活中你不会创建一个内部监听器,你会创建一个 class。

class MyMouseListener implements MouseListener {
    // define methods and behaviour
}

然后您将其添加到您的可选区域,例如:

MyMouseListener listener = new MyMouseListener()
panel1.addMouseListener(listener);
panel2.addMouseListener(listener);
panel3.addMouseListener(listener);

提示:记住MouseEvent extends from ComponentEvent that has a great method getComponent()

Returns the originator of the event.

您可以通过查看事件的鼠标点来判断该点是否仍在面板的边界内:

panel.addMouseListener(new MouseAdapter()
{
    @Override
    public void mouseExited(MouseEvent e)
    {
        Rectangle r = e.getComponent().getBounds();
        Point p = e.getPoint();

        if (p.x < 0 || p.x >= r.width
        ||  p.y < 0 || p.y >= r.height)
            panel.setBorder( null );
    }

    @Override
    public void mouseEntered(MouseEvent e)
    {
        panel.setBorder(BorderFactory.createLineBorder(Color.BLUE));
    }
});

扩展MouseAdapter更简单,只需要覆盖你想自定义的方法即可。