将调度事件摆动到多个级别的容器

发布于 2024-12-01 19:11:06 字数 3026 浏览 0 评论 0原文

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

    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 仅将事件发送到下一个直接容器,而不再发送事件。

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

Here is come code to demo my problem:
Parent class:

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

Child panel class:

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

I was hoping that once a mouseClicked event triggered in the JTextField, it will be propagated to the parent panel by using dispatchEvent. But for child panel that have JTextField, it seems that the MouseClicked event only gets to APanel. Then it prints parent of APanel is APanel!. So it appears to me that dispatchEvent only sends event to next immediate container and no more.

How can I solve this? Is there a way I can dispatch an event directly to another container?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

耳根太软 2024-12-08 19:11:06

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

看起来通过调用getParent().getParent()再上一层就可以达到想要的效果了。请记住,这是一个非常脆弱且糟糕的解决方案,因为如果您决定在 APanel 及其 JTextField 之间需要另一个组件,它就会崩溃。

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

You're seeing this behavior because MouseEvent#getSource() returns the JTextField, whose parent is the APanel. You were expecting getSource() to return APanel.

It looks like you could achieve the desired effect by calling getParent().getParent() to go up another level. Do keep in mind that this is a very brittle and poor solution because it will break if you decide that you need another component between your APanel and its JTextField.

Perhaps you can use a recursive approach to walk up the component hierarchy, calling getParent() until you've reached a PPanel, at which point you can call dispatchEvent.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文