【问题标题】:Java - MouseListener on JPanel isn't firingJava - JPanel 上的 MouseListener 没有触发
【发布时间】:2011-12-13 14:50:31
【问题描述】:

我有一个JPanel 使用BorderLayout,它有两个组件。 NORTH 中的 JLabelCENTER 中的 JList

我在面板中添加了一个MouseListener,并暂时编写了一个消息框以显示在mouseEntered 上。

问题是只有当光标进入标签所占据的区域时才会触发该事件。当鼠标进入整个面板区域时,我需要触发事件。

知道我做错了什么吗?

编辑:创建面板的代码

JPanel p = new JPanel();
p.setLayout(new BorderLayout());
p.add(new JLabel("Label"), BorderLayout.NORTH);
p.add(new JList(), BorderLayout.CENTER);
p.addMouseListener(new MouseListener(){
        @Override
        public void mouseEntered(MouseEvent e) {
            JOptionPane.showMessageDialog(null, "Entered Panel");
        }
        //Other overriden methods
        ...
    });

【问题讨论】:

  • "如果我需要显示一些代码,请告诉我。"。是的,请附上sscce
  • “创建面板的代码”您在理解 SSCCE 的哪个部分有困难?
  • 谁要求完整的程序?你读过链接吗?
  • 顺便说一句 - 请注意 JList 将消耗鼠标事件。
  • 我可能弄错了,但我确实相信具有最高 z-index 的组件首先接受 MouseEvents,如果它们什么都不做,它们(通常)会传递它们。因此,如果您的 JList 在您的 JPanel 中,它将具有更高的 z-index,并且由于 JList 处理事件,它不会被传递。

标签: java swing event-handling jpanel mouselistener


【解决方案1】:

从 jdk7 开始,您可以使用 JLayer 装饰任何 JComponent 并注册该层以接收分派给其子级的所有事件,例如

    JTable list = new JTable(30, 5);
    JComponent panel = new JPanel(new BorderLayout());
    panel.setBorder(BorderFactory.createEmptyBorder(50, 50, 50, 50));
    panel.add(new JLabel("we are label"));
    panel.add(new JScrollPane(list));
    LayerUI<JComponent> ui = new LayerUI<JComponent>() {

        @Override
        protected void processMouseEvent(MouseEvent e, JLayer<? extends JComponent> l) {
            if (e.getID() == MouseEvent.MOUSE_ENTERED) {
                System.out.println(e.getSource().getClass() + " at " + e.getPoint());
            }
        } 
    };
    JLayer<JComponent> layer = new JLayer<JComponent>(panel, ui);
    layer.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK );   

请注意,这是由 AWTEventListener 在内部处理的,正如 Rob 博客中建议的解决方案一样。与 Rob 的解决方案相比,它的优势在于它也可以在沙盒环境中工作(因为核心类 JLayer 具有必要的特权)。

对于早期的 jdk 版本,有一个 project JXLayer(SwingLabs 的一部分),它是新核心类的直接前身。它没有权限问题,因为它在内部使用稍微不同的方法来获取所有事件。

【讨论】:

    【解决方案2】:

    我认为问题在于 JList 是接收鼠标事件的组件。我不确定这是解决问题的最佳方法,但您不能也将相同的鼠标侦听器添加到 JList 中吗?

    【讨论】:

      【解决方案3】:

      任何具有 MouseListener 的组件都将接收鼠标事件,并且不会传递给面板。

      您可以为每个组件添加一个 MouseListener,但是如果您的面板设计发生变化怎么办。不要忘记您的 JList 右侧可能有一个滚动条,因此如果用户从右侧进入面板,则在鼠标移过滚动条到列表上之前不会生成事件。

      相反,您可能需要考虑使用Global Event Listener 来监听 mouseEntered 事件。那么当接收到事件时,您需要检查事件的来源是面板本身还是面板的子组件。您应该可以使用:

      SwingUtiltities.isDescendingFrom(...)
      

      帮助进行这项检查。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-04
        相关资源
        最近更新 更多