【问题标题】:Java event propagation stoppedJava 事件传播已停止
【发布时间】:2011-04-06 00:39:06
【问题描述】:

我有一个主窗口:

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");
   }
}

还有一个子 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");
   }
}

在子面板中注释掉对addMouseListener 的调用后,当我单击窗口中的任意位置(包括子级)时,父级会收到单击事件。如果我取消注释该调用并点击子面板,只有子面板会收到点击事件,它不会传播到父面板。

如何阻止事件被孩子消费?

【问题讨论】:

  • 这很奇怪......我记得有一个相反的问题,父母正在消耗孩子绑定的鼠标事件

标签: java events swing


【解决方案1】:

在 Swing 中,您通常希望被点击的组件做出响应;但是您可以将鼠标事件转发到父级,如下所示。这是一个相关的example

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();
            }
        });
    }
}

【讨论】:

【解决方案2】:

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

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

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

【讨论】:

  • 我对这种方法隐含的紧密耦合持谨慎态度。
  • 看起来我将使用 getParent() 除非我能想出一种方法来更改我的项目,这样父母和孩子都不需要处理该事件。将事件处理限制在一个组件上对我来说似乎是一个荒谬的设计决定......
猜你喜欢
  • 1970-01-01
  • 2011-01-05
  • 2012-10-10
  • 2016-05-18
  • 1970-01-01
  • 1970-01-01
  • 2011-12-09
  • 2014-03-10
  • 1970-01-01
相关资源
最近更新 更多