tags:

views:

383

answers:

3

I'm looking for a way to pass mouse events to components covered by other components. To illustrate what I mean, here's a sample code. It contains two JLabels, one is twice smaller and entirely covered with a bigger label. If you mouse over the labels, only the bigger one fires mouseEntered event however.

import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.WindowConstants;
import javax.swing.border.LineBorder;

public class MouseEvtTest extends JFrame {

    public MouseEvtTest() {
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        setLayout(null);
        setSize(250, 250);

        MouseAdapter listener = new MouseAdapter() {
            @Override
            public void mouseEntered(MouseEvent e) {
                System.out.printf("Mouse entered %s label%n", e.getComponent().getName());
            }
        };
        LineBorder border = new LineBorder(Color.BLACK);

        JLabel smallLabel = new JLabel();
        smallLabel.setName("small");
        smallLabel.setSize(100, 100);
        smallLabel.setBorder(border);
        smallLabel.addMouseListener(listener);
        add(smallLabel);

        JLabel bigLabel = new JLabel();
        bigLabel.setName("big");
        bigLabel.setBorder(border);
        bigLabel.setSize(200, 200);
        bigLabel.addMouseListener(listener);
        add(bigLabel, 0); //Add to the front
    }

    public static void main(String[] args) {
        new MouseEvtTest().setVisible(true);
    }
}

What would be the best way to fire mouse entered event on the smaller label when cursor is moved to the coordinates above it? How would it work in case where there would be multiple components stacked on top of each other? What about the remaining mouse events, like mouseClicked, mousePressed, mouseReleased, etc.?

A: 

In your listener:

bigLabel.dispatchEvent(mouseEvent);

Of course, you will have to define bigLabel as final

Bozho
A: 

Well to understand whats happening you need to understand how Z-Ordering works. As a quick overview, the component that was added last is painted first. So in your case you want to add the small component before the big component.

// add(bigLabel, 0); //Add to the front
add(bigLabel); // add to the end so it is painted first

The OverlayLayout might help explain this better and give you another option.

camickr
It may seem silly in the example code to do it like that, but it replicates my real scenario quite closely. I added the big label to the top on purpose, so to cover the small label entirely.
Emilis Panovas
Then you would be responsible for writing hit detection code your self, which means that when a mouse event is received on your big label you will need to loop through all the other Components in the panel and use the contains(...) method to see if the mouse point is in the bounds of the component. If so then you would need to create a new MouseEvent and dispatch it to that component as described above.
camickr
+1  A: 

Take a look at Alexander Potochkin's blog entry on A Well-Behaved GlassPane

Devon_C_Miller
Thanks, this helped me with a cursor problem I had with validation overlays using the JLayeredPane!
Nemi