Question

I had a different problem first, so I made this post: Java JPanel mouse listener doesn't work over its components

The answers led me to arrive at a java GlassPane. I saw the other posts on SO about this and they all point to this article: http://weblogs.java.net/blog/alexfromsun/archive/2006/09/a_wellbehaved_g.html.

I used the example from the article (FinalGlassPane.java) and set it up exactly as in the test app:

GlassPane glass = new GlassPane(this);
getRootPane().setGlassPane(glass);
GestureListener gl = new GestureListener();
glass.addMouseMotionListener(gl);
glass.addMouseListener(gl);
glass.setVisible(true);
if (glass instanceof AWTEventListener) {
    AWTEventListener al = (AWTEventListener) glass;
    Toolkit.getDefaultToolkit().addAWTEventListener(al,
            AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK);
}

But I still have the same problem, the glass prevents me from being able to click any buttons (JButton) below it.

If you've been kind enough to read my initial SO question and think glassPane is not for me, please post me an alternative solution, otherwise please tell me why this isn't working.

Thanks in advance.

EDIT: IT WORKS but stops working when I add my own MouseListener

Notice in my code I was adding my own GestureListener, I can't add my own MouseListener to this implementation - that's what makes it not work. I took those lines off and the glass pane is now working correctly.

There is this notice in the code (FinalGlassPane.java) regarding MouseListener which I don't really understand, so my new question is how can I add my own MouseListener to this glass pane?

/**
 * If someone adds a mouseListener to the GlassPane or set a new cursor
 * we expect that he knows what he is doing
 * and return the super.contains(x, y)
 * otherwise we return false to respect the cursors
 * for the underneath components
 */
@Override
public boolean contains(int x, int y) {
    if (getMouseListeners().length == 0 && getMouseMotionListeners().length == 0
            && getMouseWheelListeners().length == 0
            && getCursor() == Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)) {
        return false;
    }
    return super.contains(x, y);
}

ADDITIONAL INFO:

If I always return false in the contains(int, int) method the buttons always work, but my MouseListener on the GlassPane doesn't. If I always return "super.contains(x,y)" then the opposite happens: MouseListener on the GlassPane works but I can't click any components underneath.

FINAL EDIT So I came to the conclusion that I can't (or don't) have a way (with Java 6) to allow my Application to have 2 layers which can receive MouseListener events (mousePressed, mouseReleased) at the same time. In the end I used the solution on my original question, which was to create a custom JButton and have that add the MouseListener to each instance.

Was it helpful?

Solution

not clear from your both questions, if you you really needed convertXxx or getXxx methods from SwingUtilities

1) you can put JLabel (dispatch mouse events) to the GlassPane, this JLabel could be placed / covering whole available Rectangle from JFrame, or only required Bounds

2) you can put JLabel (dispatch mouse events) to the JViewport, this JLabel could be placed / covering whole available Rectangle from JScrollPane / JViewport, or only required Bounds

3) you can use JLayeredPane (max 6 layers)

4) you can use JLayer (Java7) based on JXLayer (for Java6 and maybe better choice)

OTHER TIPS

See the "How to Use Root Panes", in the Java Tutorials, search for the word 'redispatches' (about a page down), this has an example for something similar to what you're trying to achieve with checkboxes:

http://docs.oracle.com/javase/tutorial/uiswing/components/rootpane.html

In short you need to use SwingUtilities.getDeepestComponentAt(..) and Component.dispatchEvent(..) while translating the location of the mouse cursor.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top