【问题标题】:swing dispatch event to multiple level of containers将调度事件摆动到多级容器
【发布时间】:2011-08-26 22:20:45
【问题描述】:

这里是演示我的问题的代码: 父类:

    import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class PPanel extends JPanel{
    private APanel panel1;
    private APanel panel2;
    private APanel panel3;
    public PPanel() {
        this.setLayout(new GridLayout(0,1));
        panel1 = new APanel();
        panel1.setLayout(new GridLayout(0,1));

        panel2 = new APanel();
        panel2.setBackground(Color.yellow);
        panel2.setLayout(new GridLayout(0,1));
        panel3 = new APanel();
        panel3.setBackground(Color.green);
        //panel3.setLayout(new GridLayout(0,1));
        this.add(panel1);
        this.add(panel2);
        this.add(panel3);
        this.setBackground(Color.blue);
        this.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("Parent panel clicked!");
            }               
        });
    }
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        PPanel panel = new PPanel();
        frame.add(panel);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(new Dimension(350, 300));
        frame.setTitle("Demo");
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

子面板类:

import java.awt.Color;
import java.awt.Component;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class APanel extends JPanel{
    private JTextField tf;
    public APanel() {
        tf = new JTextField("Double click");
        tf.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("Textfiled");
                Component source = (Component) e.getSource();
                System.out.println(source.getParent());
                source.getParent().dispatchEvent(e);
            }
        });
        this.add(tf);
        this.setVisible(true);
        this.setBackground(Color.red);

        this.addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                System.out.println("Child panel clicked!");
                Component source = (Component) e.getSource();
                System.out.println("Parent container of APanel is " + source.getParent());
                if(source.getParent() instanceof PPanel)
                    source.getParent().dispatchEvent(e);
            } 
        });
    }
}

我希望一旦在 JTextField 中触发了 mouseClicked 事件,它将通过使用 dispatchEvent 传播到父面板。但是对于具有 JTextField 的子面板,似乎 MouseClicked 事件只能到达 APanel。然后它打印 APanel 的父级是 APanel!。所以在我看来,dispatchEvent 只将事件发送到下一个即时容器,而不是更多。

我该如何解决这个问题?有没有办法可以直接将事件分派到另一个容器?

【问题讨论】:

  • 另外,我看到您正在使用MouseListener,但只定义了一种方法 - 查看MouseAdapter,它提供了所有侦听器方法的空实现,允许您仅覆盖和定义您的方法'感兴趣。
  • 哦,没关系。这个例子只是我的问题的一个基本演示,所以我必须减少到简单的方法(保持简短)来展示主要问题。
  • 再次阅读我自己的评论,现在我意识到我没有全神贯注地回复您的评论。我的意思是我使用 Netbeans 编写了这个示例,因此它为我导入了所有这些方法。又快又脏!
  • 正如您所注意到的,mouseEvents 会转到最感兴趣的组件(又名:是 mouseEnabled 或具有 mouseListeners),而不是进一步 - 有一个很好的理由:想象一下所有这些事件在容器中传播无论如何,大多数时候都不感兴趣的层次结构。那么,为什么要在父节点上看到 mouseEvent 呢?
  • @kleopatra:原因是我可以使用 mouseListener MouseClicked 和 MouseDragged 来移动和拖动主(父)面板。但是,添加了所有 3 个子面板后,它们是第一个与 mouseEvent 交互的,因此我无法拖动和移动主面板。将 mouseEvent 移到父面板让我再次拥有这个能力。

标签: swing events event-handling


【解决方案1】:

您看到此行为是因为 MouseEvent#getSource() 返回 JTextField,其父级是 APanel。你期待getSource() 返回APanel

看来您可以通过调用getParent().getParent() 来提升一个级别来达到预期的效果。请记住,这是一个非常脆弱和糟糕的解决方案,因为如果您决定在您的 APanel 和它的 JTextField 之间需要另一个组件,它将会中断。

也许您可以使用递归方法向上遍历组件层次结构,调用getParent(),直到到达PPanel,此时您可以调用dispatchEvent

【讨论】:

  • 您对更好的解决方案有何建议?为 getParent().getParent() +1,因为它解决了我的问题。
  • 啊,是的。我只是在考虑使用循环并使用 instanceof 来检查将事件分派到的期望容器。事实上,我可以使用循环调度所有其他容器,直到 getParent() 返回 null!
  • 是的,您可以在所有内容上递归调用dispatchEvent 的组件层次结构,直到getParent() 返回null
  • Swing 中是否有一个实用方法可以自动向父容器分派事件?
猜你喜欢
  • 2023-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-07
相关资源
最近更新 更多