Swing でのイベントの伝播を理解するのに助けが必要です。各イベントが 1 つのコンポーネントのみによって処理されることはわかっています。したがって、outside
いくつかの子パネルを持つパネルがinside
あり、両方に mouseListeners を追加すると、そのうちの 1 つinside
が呼び出されます。それは素晴らしいことであり、それが期待される動作です。
しかし、次の状況での動作がわかりません:
MouseMotionListener を登録しinside
、MouseListener をoutside
登録します。inside
には通常の MouseEvents のリスナーがないため、すべての MouseMotionEvents を消費しoutside
、MouseEvents を受け取ることを期待していinside
ます。しかし、そうではなく、inside
どうにかして MouseMotionEvents だけでなく、すべての MouseEvents を消費します。
次のコードは、問題を示しています。
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 がこのように動作する理由はまだ不明です。しかし、どうやら、物事を機能させる唯一の方法は、イベントを手動で転送することです。私はそうします。