我需要帮助了解Swing中的事件传播。我知道每个事件只会由一个组件处理。因此,当我有一个面板
但是,我不理解以下情况的行为:
以下代码说明了问题:
outside
,它有一些子面板 inside
,并且我为它们两个都添加了mouseListeners时,inside
的监听器将被调用。这很好,也是预期的行为。但是,我不理解以下情况的行为:
inside
注册了一个MouseMotionListener,而outside
注册了一个MouseListener。我期望inside
消耗所有MouseMotionEvents,而outside
接收MouseEvents,因为在inside
上没有普通的MouseEvents监听器。但事实并非如此,inside
以某种方式消耗了所有MouseEvents,而不仅仅是MouseMotionEvents。以下代码说明了问题:
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的javadocs让我认为我的期望是正确的。因此,我需要一个不同的描述来理解它。
b) 是否有比上面草拟的解决方案更好的解决方案?
谢谢, 卡瑟琳
编辑:仍然不清楚Swing为什么会表现出这种方式。但看起来,使事情正常工作的唯一方法是手动转发事件,所以我会这样做。