How can I capture all mouse events in a JFrame/Swing? - java

I have a JFrame that has a large number of changing child components. (Many layers) Is there any way to add a listener for all mouse events? Something like KeyEventDispatcher?

Use an AWTEventListener to filter out the MouseEvents:
long eventMask = AWTEvent.MOUSE_MOTION_EVENT_MASK + AWTEvent.MOUSE_EVENT_MASK;
Toolkit.getDefaultToolkit().addAWTEventListener( new AWTEventListener()
{
public void eventDispatched(AWTEvent e)
{
System.out.println(e);
}
}, eventMask);

You could add a GlassPane over your entire JFrame, add a MouseInputAdapter to it to grab all possible mouse events, and then use [SwingUtilities.getDeepestComponentAt()][3] to get the actual component and [SwingUtilities.convertMouseEvent()][4] to delegate the mouse event from the glass pane to the actual component.
However, I'm not sure of the performance impact of this - unlike KeyEventDispatcher, which just needs to fire an event whenever a key is pressed, multiple events are generated as the user moves the mouse - and unlike KeyEventDispatcher, you need to re-send the event to the lower component for it to handle it.
(Sorry - stackoverflow isn't handling the links to the SwingUtilities methods correctly... links are showing below rather than in the text.)
[3]: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/SwingUtilities.html#getDeepestComponentAt(java.awt.Component, int, int)
[4]: http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/SwingUtilities.html#convertMouseEvent(java.awt.Component, java.awt.event.MouseEvent, java.awt.Component)

You have to use JFrame's glassPane:
http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JFrame.html#getGlassPane()
Just get the glass pane of a JFrame with frm.getGlassPane() and use addMouseListener() on it to capture all mouse event inside the window.

Implement all mouse-related listeners in a class, and register that class as the handler for all mouse related events
Mouse Related interfaces would be
MouseListener
MouseMotionListener
MouseWheelListener

You might want to implement a subclass of MouseAdapter, an abstract class that provides empty implementations of all of the methods defined in the Mouse*Listener Interfaces. Once you do that, you can register it with your child components as a MouseListener when they are created. As you indicate that your components are 'changing,' you will want to make sure the you also unregister your listener if you hope to release your components during the lifecycle of your JFrame.

Related

Java GUI Mouse Listener

could you guys help me out.
How do we order the process of Mouselistener?
I mean, I want my mouseEntered and mouseExited working after I click on my one of my JPanel.
If I understand your question, you want to enable a MouseMotionListener only after a component is clicked...
Basically, in your MouseListener's mousePressed method, you would simply add your MouseMotionListener
Now remember, mouse listeners consume events, that is a child component will hide mouse events that occur on it from it's parent container
Take a look at How to write mouse listeners for more details

Change value when mouse is clicked

I have JTextfield. Now I want to change value when in this component is mouse clicked. For example: score (2 big JTextField) and when I click to one of these field it increase the value from 0:0 to 1:0.
Should I implement MouseListener or there is some easy way how I can do this? In mouse listener I need override just one method mouseClick and other method will be empty.
And another question: when should I implement MouseListener? e.getButton() return always 1 for left button and 3 for right button?
Should I implement MouseListener or there is some easy way how I can do this? In mouse listner I need override just one method mouseClick and other method will be empty.
Use a MouseAdapter.
An abstract adapter class for receiving mouse events. The methods in this class are empty. .. Extend this class to create a MouseEvent (including drag and motion events) or/and MouseWheelEvent listener and override the methods for the events of interest.
Now I want to change value when in this component is mouse clicked
JTextComponents are Focusable, look for FocusListener
Implementing MouseListener on your class is one way to do it, but if you just want to react to clicks, it's easier to use an anonymous class extending MouseAdapter
textField.addMouseListener(new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {
// do your thing here
}
});
As for the second question, the API documentation quite nicely documents the return values of MouseEvent.getButton().

JPanel does not generate MouseEvents when cursor is on child components

It is a bit strange for me but JPanel does not generate MouseEvents when cursor is on child components: JTextField and JToolBar but it generates MouseEvents when cursor is on JLabel. Could someone explaind me why? Is there any way to force JPanel to generate events even if mouse is on child components?
The event dispatcher will forward mouse events to the listeners registered to the component that is returned by the package-level getMouseEventTarget method in Container. This will be called on your JFrame, and, as the JavaDoc indicates, it:
Fetchs the top-most (deepest) lightweight component that is interested in receiving mouse events.
The event dispatcher then takes this top-most component (your JTextField, for example) and sends events to all of its listeners only. They do this in order to avoid having to broadcast these events to all of the components that may be layered within a Swing container. MouseEvents, as you can imagine, are very chatty, what with all of the mouseEntered, mouseDragged, and mouseMoved events that are dispatched for all of the MouseListener and MouseMotionListener implementations potentially out there. The processing to find all listeners and then fire events to all of them in the hierarchy would be time consuming.
The assumption is also that for classes like JTextField and JButton, etc., the default mouse handling is all that one would need. If you want to handle mouse actions differently (ie, changing color on a mouseEntered/mouseExited), you can add a MouseListener to these widgets as you need to.
For your processing, I would suggest simply adding your JPanel as a MouseListener to your top level components if you need to handled these events.
you may want to have the child components (JTextField, JToolBar, etc) listen for the mouse events from the jpanel and/or forward the mouse events to the child components.
Could someone explain why?
Component mouse events are handled by processMouseEvent(), which says
Mouse events are enabled when one of the following occurs:
A MouseListener object is registered via addMouseListener.
Mouse events are enabled via enableEvents.
You can use getMouseListeners() to see the difference.

MouseListener on JFrame

I want to be notified of mouse events (specifically the mouse entered and exited events) on my JFrame. But when i add a mouselistener to it i get the events on the borders of the frame not the entire frame with it's contents.
Any ideas as to why?
EDIT : Or at least do you have an alternative? I want a "gloabal" way to catch mouse events on the JFrame. Maybe a mouselistener is not the answer.
You can get all events and check if their source is a component in the JFrame.
See Toolkit.addAWTEventListener
There is an invisible component that overlays the whole GUI, the "glass pane". You can attach your listeners to that. Example:
JFrame frame = new JFrame();
Component glassPane = frame.getGlassPane();
glassPane.addMouseListener(myListener);
If you want your intercepted events to pass through to the underlying components, you can redispatch them. For example:
public void mouseMoved(MouseEvent e) {
redispatchMouseEvent(e, false);
}
Because the contents ( probably a JPanel ) are "shadowing" and consuming the events and they don't reach the JFrame.
What you can do is to add the same listener to all the children. There should be a better way though.
An alternative to AWTEventListener is to push an EventQueue. This has the advantage that applets and WebStart application can do this.

Swing: Adding listener to a component and ALL its decoration?

Can I add a listener (let's say MouseAdapter) to a Swing component
and all it's internal decoration components?
So that when a JInternalFrame is moved by the mouse
(by dragging its window title bar), it would give me following events:
mousePressed event,
mouseDragged event,
mouseReleased event.
Currently, I receive none of the above events when dragging
JInternalFrame.
I hope there is some standardized solution, but I couldn't find any.
EDIT:
Some people suggest using ComponentListener, but that wouldn't do for
me. I need to know, when the user stops dragging (mouseReleasedEvent),
not when the component moves.
Yes, you can add a listener to all a container's components. getComponents and add the listener. You should be able to manage to do this recursively. You can also use ContainerListener to check for adding and removing components.
However, MouseListener and MouseMotionListener behave strangely in that the event normally bubbles up to the parent, but does not do so if a listener is present (how is that for hopeless design?).
Your choices are:
Recursively adding listeners (bad, see above)
Adding listeners to specific components (fragile)
Adding a "glass pane" (a messy hack)
Adding an AWTEventListener to Toolkit (requires permissions)
Pushing an EventQueue and checking through events (doesn't work of Opera and Safari apparently; stops system copy-and-paste and applet dragging from working)
Use ComponentListener?
I found out how it could be done, but something tells me, it's a dirty hack ;)
Well, it works, but who can give me the guarantee that it works everywhere?
// ctor goes here {
InternalFrameUI thisUI = getUI();
((BasicInternalFrameUI) thisUI).getNorthPane()
.addMouseMotionListener(new MyMouseListener());
// }
NorthPane turns out to be the window title bar.
You should probably use a MouseMotionListener instead of a MouseListener.
In the JInternalFrame API documentation, it says:
Generally, you add JInternalFrames to
a JDesktopPane. The UI delegates the
look-and-feel-specific actions to the
DesktopManager object maintained by
the JDesktopPane.
Maybe you should add your listener to the JDesktopPane.
MouseListener/MouseMotionListener wont detect when dragging a JInternalFrame. Your best bet here to detect movement is using a ComponentListener on the JInternalFrame itself.

Categories