java - 为什么当我进入或退出 JDialog 时,mouseExited 和 mouseEntered 方法同时运行?

标签 java swing mouseevent jdialog

是的,这个问题已经发布在 JavaRanch 上,但我不太理解它们。

我有 JDialog,它添加了 MouseListener,如下所示:

super.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseExited(MouseEvent e) {
                if (e.getSource() instanceof ConnectionTreeTooltip) {
                    System.out.println("mouse exited!!!!!!!!!!!!!!!!!!=" + e);
                    // hideTooltip();
                }
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                if (e.getSource() instanceof ConnectionTreeTooltip) {
                    System.out.println("mouse entered!!!!!!!!!!!!!!!!!!=" + e);
                    // hideTooltip();
                }
            }
        });

ConnectionTreeTooltip 就是这个jdialog。 问题在于,每当鼠标进入或退出 JDialog 时,都会调用这两种方法。他们只是一起跑。

我的JDialog的代码:

public class ConnectionTreeTooltip extends JDialog {
...........
public ConnectionTreeTooltip(ConnectionsTree connectionsTree) {
        super(connectionsTree.getMainFrame(), "", false);
        super.setUndecorated(true);
        super.setFocusableWindowState(false);
.............
super.getContentPane().add(scrollPane);
        super.pack();
    }

connectionsTree.getMainFrame() 返回 JFrame 的实例。

编辑这是完整的代码:

public ConnectionTreeTooltip(ConnectionsTree connectionsTree) {
        super(connectionsTree.getMainFrame(), "", false);
        super.setUndecorated(true);
        super.setFocusableWindowState(false);

        this.connectionsTree = connectionsTree;
        JPanel contentPane = (JPanel) super.getContentPane();
        contentPane.setBorder(BorderFactory.createEtchedBorder(EtchedBorder.LOWERED, Color.blue, Color.red));
        tipLabel = new JLabel();
        // by default, JLabel is not focusable.
        tipLabel.setFocusable(true);
        tipLabel.setBackground(Color.WHITE);
        scrollPane = new JScrollPane(tipLabel) {
            @Override
            public Dimension getPreferredSize() {
                return preferredSizeOfScrollPane;
            }
        };
        scrollPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 1, 1));
        super.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseExited(MouseEvent e) {
                if (e.getSource() instanceof ConnectionTreeTooltip) {
                    System.out.println("mouse exited!!!!!!!!!!!!!!!!!!=" + e);
                    // hideTooltip();
                }
            }

            @Override
            public void mouseEntered(MouseEvent e) {
                if (e.getSource() instanceof ConnectionTreeTooltip) {
                    System.out.println("mouse entered!!!!!!!!!!!!!!!!!!=" + e);
                    // hideTooltip();
                }
            }
        });
        tipLabel.addKeyListener(new KeyAdapter() {
            @Override
            public void keyReleased(KeyEvent e) {
                // tipLabel can key events only if it is visible and focused
                if (e.getKeyCode() == 32) {
                    unFocusTipLabel();
                }
            }
        });
        super.getContentPane().add(scrollPane);
        super.pack();
    }

为什么会这样,我的 JDialog 或我的 MouseListener 有什么问题?

谢谢!

最佳答案

很可能您的 JDialog 内部包含一个组件,该组件会从对话框本身窃取鼠标监听器,因此当您的鼠标进入对话框时,对话框会感应到鼠标进入,但随后鼠标会立即进入对话框的组件( JScrollPane 可能),mouselistener 感觉到您已经离开对话框并进入了它的子组件。

比如我的SSCCE:

import java.awt.event.*;
import javax.swing.*;

public class MouseListenerTest {
   public static void main(String[] args) {
      final JFrame mainFrame = new JFrame("My Frame");
      mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      mainFrame.add(new JPanel() {
         {
            add(new JButton(new AbstractAction("Show Dialog") {

               @Override
               public void actionPerformed(ActionEvent arg0) {
                  ConnectionTreeTooltip cttt = new ConnectionTreeTooltip(
                        mainFrame);
                  cttt.setVisible(true);
               }
            }));
         }
      });
      mainFrame.pack();
      mainFrame.setLocationRelativeTo(null);
      mainFrame.setVisible(true);

   }
}

class ConnectionTreeTooltip extends JDialog {

   public ConnectionTreeTooltip(JFrame mainFrame) {
      super(mainFrame, "", false);
      setUndecorated(true);
      setFocusableWindowState(false);
      add(new JScrollPane(new JTextArea(20, 40)));
      ((JPanel)getContentPane()).setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
      pack();
      addMouseListener(new MouseAdapter() {
         @Override
         public void mouseExited(MouseEvent e) {
            if (e.getSource() instanceof ConnectionTreeTooltip) {
               System.out.println("mouse exited!!!!!!!!!!!!!!!!!!=" + e);
               // hideTooltip();
            }
         }

         @Override
         public void mouseEntered(MouseEvent e) {
            if (e.getSource() instanceof ConnectionTreeTooltip) {
               System.out.println("mouse entered!!!!!!!!!!!!!!!!!!=" + e);
               // hideTooltip();
            }
         }
      });
   }
}

现在困难的部分是弄清楚如何使用 GlassPane 获取鼠标进入/离开信息,但仍允许将鼠标事件传递到玻璃 Pane 下方的对话框。


编辑

是的,解决方案是使用玻璃板:

import java.awt.event.*;
import javax.swing.*;

public class MouseListenerTest {
   public static void main(String[] args) {
      final JFrame mainFrame = new JFrame("My Frame");
      mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      mainFrame.add(new JPanel() {
         {
            add(new JButton(new AbstractAction("Show Dialog") {

               @Override
               public void actionPerformed(ActionEvent arg0) {
                  ConnectionTreeTooltip cttt = new ConnectionTreeTooltip(
                        mainFrame);
                  cttt.setVisible(true);
               }
            }));
         }
      });
      mainFrame.pack();
      mainFrame.setLocationRelativeTo(null);
      mainFrame.setVisible(true);

   }
}

class ConnectionTreeTooltip extends JDialog {

   public ConnectionTreeTooltip(JFrame mainFrame) {
      super(mainFrame, "", false);
      setUndecorated(true);
      setFocusableWindowState(false);
      add(new JScrollPane(new JTextArea(20, 40)));
      ((JPanel) getContentPane()).setBorder(
            BorderFactory.createEmptyBorder(4, 4, 4, 4));
      pack();

      JComponent glassPane = (JComponent) getGlassPane();
      glassPane.setVisible(true);

      glassPane.addMouseListener(new MyMouseAdapter());
   }

   private class MyMouseAdapter extends MouseAdapter {

      @Override
      public void mouseExited(MouseEvent e) {
         System.out.println("mouse exited");
      }

      @Override
      public void mouseEntered(MouseEvent e) {
         System.out.println("mouse entered");
      }
   }
}

关于java - 为什么当我进入或退出 JDialog 时,mouseExited 和 mouseEntered 方法同时运行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18643615/

相关文章:

java - 如何将参数传递给 Hibernate 的 subselect 标签?

java - 在我的手机游戏中添加图像

java - 两个列表中的共同元素,无需完全遍历

java - 如何打造专业定制的Java Swing Gui?

java - 如何将 JPopup 移动到 Glasspane

java - 在 JTextPane 中设置字体宽度

Java Swing JPanel。如何绘制形状?

javascript - 使用基于位置的 MouseEvent 触发输入 slider 的更改

objective-c - cocoa mousedown 在一个窗口上,鼠标在另一个窗口上向上

canvas - D3 Canvas 地球仪鼠标事件