2

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?

Nate W.
  • 9,141
  • 6
  • 43
  • 65
bili
  • 610
  • 2
  • 9
  • 20
  • Also, I see you're using `MouseListener` but only defining one method - check out [MouseAdapter](http://download.oracle.com/javase/6/docs/api/java/awt/event/MouseAdapter.html) which provides empty implementations of all the listener methods, allowing you to override and define only the methods you're interested in. – Nate W. Aug 26 '11 at 22:36
  • oh never mind that. This example is just a basic demo of my problem so I have to cut down to bare methods (keep it short) to show the main problem. – bili Aug 26 '11 at 22:38
  • read my own comment again now i realized I haven't responded your comment in full attention. What I meant was that I used Netbeans to write this example so it imports all those methods for me. Quick and dirty! – bili Aug 27 '11 at 02:00
  • as you noticed, mouseEvents go to the top-most component which is interested (aka: is mouseEnabled or has mouseListeners) and not further - for a good reason: just imagine all those events traveling up the container hierarchy which most of the time isn't interested anyway. So, why do you want to see the mouseEvent on the parent? – kleopatra Aug 27 '11 at 10:19
  • @kleopatra: the reason is that I can move&drag the main (parent) panel by using the mouseListener MouseClicked and MouseDragged. However, with all 3 children panels added in, they are the first to interact with the mouseEvent therefore I can't drag & move the main panel. Moving mouseEvent to the parent panel let me have this ability again. – bili Aug 27 '11 at 14:02
  • thanks for explaining your use-case :-) – kleopatra Aug 27 '11 at 15:11

1 Answers1

2

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.

Nate W.
  • 9,141
  • 6
  • 43
  • 65
  • What do you suggest for a better solution? +1 for getParent().getParent() as it solves my problem. – bili Aug 26 '11 at 22:33
  • Ah, yeah. I was just thinking about using a loop and use instanceof to check for the desire container to dispatch the event to. In fact, I can use a loop to dispatch to all other containers until getParent() returns null! – bili Aug 26 '11 at 22:46
  • Yeah, you could just recurse up the component hierarchy calling `dispatchEvent` on everything until `getParent()` returns `null`! – Nate W. Aug 26 '11 at 22:51
  • Is there a utility method in Swing that automatically dispatches event to parent containers? – Sai Dubbaka Jul 19 '15 at 18:47