Show image on glasspane while mouse button is down

My main window has several components, including an image thumbnail. While the user holds down the left mouse button on the thumbnail, I want the whole window to be overlaid with the full version of the image. The glass pane seems perfect. Just one problem:

As soon as the user moves the mouse while holding it down,
the image on the glass pane image vanishes.

This happens because AWT invents a mouse_exited for the thumbnail on line 4103 of java.awt.Container, method trackMouseEnterExit:

retargetMouseEvent(targetLastEntered, MouseEvent.MOUSE_EXITED, e);

How can I get around this "feature"?
How can I have the overlay remain visible while the mouse is down?

When you try the application this method gets called even when the mouse has NOT exited from anything. At most it has exited the small image. But certainly not the large overlaid image. And it is the large overlaid image that is the source of the exit.

Fred Hansen

With my new understanding of what is happening, I have been able to work around the problem. It would be preferable to not have the problem.

source code for the test

The attached source code is that for the demo in my previous note.

Some detail may help: The program has three addMouseListener() calls --
one for the thumbnail image, one for the large overlaid image, and one for the GlassFrame.
The glass frame is overlaid over the entire window with

The glass frame fields all mouse events and forwards them to one of the two images.
(I would prefer not to add listeners to the images and rely on the mouse forwarding.
But dispatchEvent only sends events to listeners that have been added,)

At the time of the error, the mouse is down
and the glass frame is about to receive a MOUSE_DRAGGED event.Before that event is sent to GTest, the methodContainer.LightweightDispatcher.trackMouseEnterExi t
creates and dispatches an artificial MOUSE_EXITED event. See the stack trace below.

There are two ways it might make sense to create an artificial MOUSE_EXITED:
It might be argued that the mouse has exited the thumbnail image because it has been overlaid.
Or perhaps the glassframe is being exited in favor of the image that now occupies its entirety. BUT NO. The MOUSE_EXITED is generated for the large image,
the one component that the mouse CANNOT be exiting.
The one component that has just been entered.

It may be that the "source" of a MOUSE_EXITED event is not the Component that has been exited from, but rather the new Component where the mouse now resides. It seems that there is no reliable way to determine what Component is being exited from!

Been looking over your code, but I don't have the time yet to fully grok it. Question though, is what is it trying to accomplish with this set up? Are you trying to show the enlarged picture on click, and then get rid of it if the mouse moves away from original thumbnail rectangle boundaries? I'm betting that this problem can be simplified even more, but again, haven't yet had the time to do it. Perhaps you can? Much luck!

What the demo is trying to do

The demo tries to show the large pic while the mouse is down, whether it moves or not.
This works if "fail" is not checked.
But if fail is checked, the image immediately goes away as soon as the mouse moves.

The problem is a MOUSE_EXITED auto-generated in line 4103 of Container.
When "fail" is not checked, the app ignores MOUSE_EXITED.
When "fail" is checked, the app reacts to MOUSE_EXITED.
(The value of "fail" is tested on line 79)

Lines 175-222 can be ignored. They generate a log of mouse events if line 221 is not commented out.

After further coding and consideration, the problem is in my code. The GlassFrame is fielding all mouse activity and forwarding it to where it thought it should go. In the case I was objecting to, its thoughts and my expectations differed.

Working code for GlassFrame

The task is to raise a full-window image for the duration of having a mouse down on a button. The button will be hidden by the window. I want a general solution so I can have various window overlays, each implemented without special consideration for being an overlay.

The difficulty is that when a mouse is pressed subsequent events go to it instead of the overlay that has covered it.

My first attempt was GTest_nv, a naive solution. It requires the button to forward mouse events to the overlay while the mouse is down. Works fine. But requires the button to do unnatural mouse forwarding.

My second attempt, GTest_ok, installed a permanent glasspane that catches all mouse events and forwards them appropriately. This works fine. (It also demonstrates the spurious mouse events that started this thread.) My feeling was that this was a bit of a heavy-handed solution.

I am finally pleased by my third attempt, GTest_better. This one treats almost all mouse events naturally. The one wrinkle is to catch mouse events from the button object where the mouse was clicked to install an overlay. The method to set an occupant into the glass pane has two arguments. First is the Component to overlay the window. Second is the event that has caused the application to make the overlay. See the call to setOccupant in this code

Mouse events are logged via the MouseLog class. It offers a LoggingAdapter that works much like MouseAdapter, but also logs events. The method names are all single words (pressed, released, moved, ...). The usual MouseAdapter methods merely log the event and call the single-word-named method.

The attachments include the three GTest versions and MouseLog. The two images will be attached to my next post.

Images for the code

A medlar is a fruit related to roses; its fruit is like a rose hip, only bigger. To make jelly from the fruit you first let it rot on the tree. The medlar in the picture is in the Elizabethan Herb Garden, Mellon Park, Pittsburgh, PA, USA.

The attached images need to reside in the class directory with GTest_xx.class.

As you will note, there are two packages:

com.physpics.tools with MouseLog
com.physpics.test with the other files