java - 子组件中的 MouseMotionListener 禁用父组件中的 MouseListener

标签 java swing events mouse-listeners

我需要帮助来理解 Swing 中的事件传播。我知道每个事件只由一个组件处理。因此,当我有一个面板 outside 和一些子面板 inside 并且我将 mouseListeners 添加到它们两个时, inside 将被调用.这很好,这是预期的行为。

但我不明白以下情况下的行为: inside 注册一个 MouseMotionListener,outside 注册一个 MouseListener。我希望 inside 消耗所有 MouseMotionEvents 和 outside 接收 MouseEvents,因为 inside 上没有普通 MouseEvents 的监听器。但事实并非如此,inside 以某种方式消耗了所有 MouseEvent,而不仅仅是 MouseMotionEvent。

下面的代码说明了这个问题:

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

public class EventTest {
public static void main(String... args) {
    SwingUtilities.invokeLater(new Runnable(){
        @Override
        public void run() {
            JComponent inside = new JPanel(); 
            inside.setBackground(Color.red);
            inside.setPreferredSize(new Dimension(200,200));
            MouseMotionListener mm = new MouseMotionListener() {
                @Override
                public void mouseDragged(MouseEvent arg0) {
                    System.err.println("dragged");                      
                }
                @Override
                public void mouseMoved(MouseEvent arg0) {
                    System.err.println("moved");
                }
            };
            // next line disables handling of mouse clicked events in outside 
            inside.addMouseMotionListener(mm); 

            JComponent outside = new JPanel();
            outside.add(inside);
            outside.setPreferredSize(new Dimension(300,300));
            outside.addMouseListener( new MouseAdapter() {
                public void mouseClicked(MouseEvent e) {
                    System.err.println("clicked");
                }
            });

            JFrame frame = new JFrame();
            frame.add(outside);
            frame.pack();
            frame.setVisible(true);
        }
    });
    }
}

我可以通过在 inside 上为父组件可能感兴趣的所有事件注册一个监听器来解决这个问题,然后调用 dispatchEvent 将事件转发给父组件。

a) 有人可以指点我一些描述这种行为的文档吗? MouseEvent 的 javadoc 让我觉得我的期望是正确的。所以,我需要一个不同的描述来理解它。

b) 是否有比上面概述的解决方案更好的解决方案?

谢谢, 凯瑟琳

编辑:目前还不清楚为什么 Swing 会这样。但看起来,让这些东西正常工作的唯一方法是手动转发事件,我会这样做。

最佳答案

a) 通过 design ,只有在子组件上没有鼠标监听器时,Java 鼠标事件才会“冒泡”。

b) 您可以转发事件到另一个组件,如图所示here及以下。

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

public class EventTest {

    public static void main(String... args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                final JComponent outside = new JPanel();
                JComponent inside = new JPanel();
                inside.setBackground(Color.red);
                inside.setPreferredSize(new Dimension(200, 200));
                inside.addMouseMotionListener(new MouseAdapter() {

                    @Override
                    public void mouseDragged(MouseEvent e) {
                        System.err.println("dragged");
                    }

                    @Override
                    public void mouseMoved(MouseEvent e) {
                        System.err.println("moved inside");
                        outside.dispatchEvent(e);
                    }
                });

                outside.add(inside);
                outside.setPreferredSize(new Dimension(300, 300));
                outside.addMouseMotionListener(new MouseAdapter() {

                    @Override
                    public void mouseMoved(MouseEvent arg0) {
                        System.err.println("moved outside");
                    }
                });

                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(outside);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}

关于java - 子组件中的 MouseMotionListener 禁用父组件中的 MouseListener,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11831029/

相关文章:

java - OpenCV 不适用于 JavaFx

Java:我如何知道我的 TableModel 是否有 TableModelListener?

java: 在源组件之外释放鼠标时结束 mouseDragged

java - 使用 POI 将 HTML 数据表导出到 Excel

java - Java中单个字符大写

java - 在GAE中获取用户昵称

Angular 2 : Pressing the enter key triggers a method and I don't know how to stop it

java - 使用返回不同类型的 SpelExpressionParser 解析表达式的方法

jquery:在可点击的 div 中保持 <a> 链接可点击

javascript - 多个元素的事件监听器,当存储为变量时