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

Kat*_*ann 9 java events swing mouse-listeners

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

但我不理解以下情况中的行为: inside注册MouseMotionListener并outside注册MouseListener.我希望inside使用所有MouseMotionEvents并outside接收MouseEvents,因为没有正常MouseEvents的监听器inside.但事实并非如此,inside不仅仅消耗MouseMotionEvents的所有MouseEvent.

以下代码说明了该问题:

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);
        }
    });
    }
}
Run Code Online (Sandbox Code Playgroud)

我可以通过inside为父组件可能感兴趣的所有事件注册侦听器然后调用dispatchEvent将事件转发给父组件来解决此问题.

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

b)有没有比上面描述的解决方案更好的解决方案?

谢谢,凯瑟琳

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

tra*_*god 8

a)通过设计,只有在子组件上没有鼠标侦听器时,Java鼠标事件才会"冒泡".

b)您可以转发事件到其他组件,如这里及以下.

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);
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)