Java事件传播已停止

tak*_*eek 8 java events swing

我有一个主窗口:

public class MainPanel extends JFrame implements MouseListener {

   public MainPanel() {
      setLayout(new FlowLayout());
      setDefaultCloseOperation(EXIT_ON_CLOSE);
      addMouseListener(this);

      ChildPanel child = new ChildPanel();
      add(child);

      JPanel spacer = new JPanel();
      spacer.setPreferredSize(new Dimension(50, 50));
      add(spacer);

      pack();
      setLocationRelativeTo(null);
   }

   @Override
   public void mouseClicked(MouseEvent e) {
      System.out.println("Mouse click event on MainPanel");
   }
}
Run Code Online (Sandbox Code Playgroud)

和一个孩子JPanel:

public class ChildPanel extends JPanel implements MouseListener {

   public ChildPanel() {
      setBackground(Color.RED);
      setPreferredSize(new Dimension(200, 200));
      //addMouseListener(this);
   }

   @Override
   public void mouseClicked(MouseEvent e) {
      System.out.println("Mouse click event on ChildPanel");
   }
}
Run Code Online (Sandbox Code Playgroud)

通过addMouseListener在子面板中注释掉的调用,当我单击窗口中的任何位置(包括在子窗口上)时,父级会收到单击事件.如果我取消注释该调用并单击子面板,则只有子节点接收到click事件,并且它不会传播到父节点.

如何阻止儿童食用该事件?

tra*_*god 5

在Swing中,您通常希望单击的组件响应; 但您可以将鼠标事件转发给父级,如下所示.这是一个相关的例子.

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JPanel;

/** @see https://stackoverflow.com/questions/3605086 */
public class ParentPanel extends JPanel {

    public ParentPanel() {
        this.setPreferredSize(new Dimension(640, 480));
        this.setBackground(Color.cyan);
        this.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("Mouse clicked in parent panel.");
            }
        });
        JPanel child = new JPanel();
        child.setPreferredSize(new Dimension(320, 240));
        child.setBackground(Color.blue);
        child.addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("Mouse clicked in child panel.");
                ParentPanel.this.processMouseEvent(e);
            }
        });
        this.add(child);
    }

    private void display() {
        JFrame f = new JFrame("MouseEventTest");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(this);
        f.pack();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new ParentPanel().display();
            }
        });
    }
}
Run Code Online (Sandbox Code Playgroud)


The*_*ist 4

我认为你不能。我相信只有一个组件接收事件是 Swing 设计原则。

但是,您可以获得所需的行为,但将 传递给JFrameChildPanel调用其mouseClicked(MouseEvent)或任何您想要的方法。或者直接获取父组件。

   @Override
   public void mouseClicked(MouseEvent e) {
      System.out.println("Mouse click event on ChildPanel");
      this.frame.mouseClicked(e);
      getParent().mouseClicked(e);
   }
Run Code Online (Sandbox Code Playgroud)

  • 我对这种方法隐含的紧密耦合持谨慎态度。 (3认同)
  • 看起来我将使用 getParent() ,除非我能想出一种方法来更改我的项目,这样父级和子级都不需要处理该事件。对我来说,将事件处理限制在一个组件上似乎是一个荒谬的设计决定...... (2认同)