3

Below is SSCCE to describe my problem.

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

public class APanel extends JPanel{

public APanel() {

    this.setVisible(true);
    this.setBackground(Color.red);
    this.addMouseListener(new MouseListener() {

        public void mouseClicked(MouseEvent e) {
            if(e.getClickCount()==2)
            {

            }
            System.out.println("Child panel clicked!");
        }
        public void mousePressed(MouseEvent e) { }
        public void mouseReleased(MouseEvent e) {}
        public void mouseEntered(MouseEvent e) { }
        public void mouseExited(MouseEvent e) {}
    });
  }
}


    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();
        panel2 = new APanel();
        panel2.setBackground(Color.yellow);
        panel3 = new APanel();
        panel3.setBackground(Color.green);
        this.add(panel1);
        this.add(panel2);
        this.add(panel3);
        this.setBackground(Color.blue);
         this.addMouseListener(new MouseListener() {
            public void mouseClicked(MouseEvent e) {
                System.out.println("Parent panel clicked!");
            }
            public void mousePressed(MouseEvent e) { }
            public void mouseReleased(MouseEvent e) {}
            public void mouseEntered(MouseEvent e) { }
            public void mouseExited(MouseEvent e) {}
        });
    }

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

How can I do the following:

  • If e.getClickCount()==1 then the parent MouseListener will active and it will print "parent panel clicked!".
  • If e.getClickCount()==2 then the children MouseListner will active and print out "child panel clicked!".

    Edit1: Closer to the proposed solution.

    import java.awt.*;
    import java.awt.event.*;
    import javax.swing.JPanel;
    import javax.swing.Timer;
    
    public class APanel extends JPanel {
    
    private static final long serialVersionUID = 1L;
    private Point pt;
    
    public APanel() {
        timer.setRepeats(false);
        addMouseListener(new MouseAdapter() {
    
            @Override
            public void mouseClicked(MouseEvent e) {
                if (timer.isRunning() && !e.isConsumed() && e.getClickCount() > 1) {
                    System.out.println("double from child");
                    pt = null;
                    timer.stop();
                } else {
                    pt = e.getPoint();
                    Component component = (Component)e.getSource();
                    component.getParent().dispatchEvent(e);
                    timer.restart();
                }
            }
        });
        setBackground(Color.red);
        setVisible(true);
    }
    
    private Timer timer = new Timer(200, new ActionListener() {
    
        @Override
        public void actionPerformed(ActionEvent e) {
            //System.out.println("single from child");
        }
    });
    

    }

In case, a mouseEvent needs to pass through multiplevel of containers, this link might be of interest.

Community
  • 1
  • 1
bili
  • 610
  • 2
  • 9
  • 20

2 Answers2

3

If you elect to interpret double clicks, consider using the user's preferred interval, as suggested here.

Toolkit.getDefaultToolkit().getDesktopProperty("awt.multiClickInterval");
Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
2

I think (as I know) that not is possible redirect Mouse event from child to its parent, just get parent from Component that is under the MouseCursor, or get parent from Component that's received Events from MouseClick

sure maybe someone can help you with that :-), but here is code which you needed for success with that

parent:

import java.awt.*;
import javax.swing.*;

public class PPanel extends JPanel {

    private static final long serialVersionUID = 1L;
    private APanel panel1;
    private APanel panel2;
    private APanel panel3;

    public PPanel() {
        setLayout(new GridLayout(0, 1));
        panel1 = new APanel();
        panel2 = new APanel();
        panel2.setBackground(Color.yellow);
        panel3 = new APanel();
        panel3.setBackground(Color.green);
        add(panel1);
        add(panel2);
        add(panel3);
        setBackground(Color.blue);
    }

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

            @Override
            public void run() {
                JFrame frame = new JFrame();
                PPanel panel = new PPanel();
                frame.add(panel);
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setPreferredSize(new Dimension(350, 300));
                frame.setTitle("Demo");
                frame.setLocationRelativeTo(null);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}

Child:

import java.awt.*;
import java.awt.event.*;
import javax.swing.JPanel;
import javax.swing.Timer;

public class APanel extends JPanel {

    private static final long serialVersionUID = 1L;
    private Point pt;

    public APanel() {
        timer.setRepeats(false);
        addMouseListener(new MouseAdapter() {

            @Override
            public void mouseClicked(MouseEvent e) {
                if (timer.isRunning() && !e.isConsumed() && e.getClickCount() > 1) {
                    System.out.println("double from child");
                    pt = null;
                    timer.stop();
                } else {
                    pt = e.getPoint();
                    timer.restart();
                }
            }
        });
        setBackground(Color.red);
        setVisible(true);
    }

    private Timer timer = new Timer(400, new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("single from child");
        }
    });
}
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • Nice! I see you use timer to detect double click which I only use e.getClickCount(). I manage to send the signal from the child to the parent container. But if I do double click, the child Listener will kick in as well. I think I need to look at whole of my code base and see if I can reorganise it for a better layout. I got that code and idea of sending event to parent from here [link](stackoverflow.com/questions/3818246/passing-events-to-parent). See my edit from OP for the code for the child panel. – bili Aug 25 '11 at 00:30