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.
Related
I have a working JPanel extended class that handles all the mouse and keyboard events. I put that panel into a JSplitPane with another JPanel. Now none of my mouse and keyboard events are firing off in my original JPanel.
My theory is that the JPSplitPane now takes the events. Is there a way to easily make it so those events are passed down to my JPanel just like before?
Upon my research I found out that the mouse events are handled by the first possible MouseListener (in this case the JSplitPane) so all I had to do was this...
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,leftColumn, analyzerPanel);
splitPane.addMouseListener(analyzerPanel);
splitPane.addMouseMotionListener(analyzerPanel);
splitPane.addMouseWheelListener(analyzerPanel);
splitPane.addKeyListener(analyzerPanel);
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.
I am trying to remove the drag bar across the top of the JFrame. I would like to keep the minimize maximize and close options that appear on this bar available. What I was thinking was to remove the bar (and icons). Then add the icons as embedded images, that implement the JFrame actionlistener. It would also be necessary for this to work with JInternalFrames. Any help would be greatly appreciated.
You need to step back and understand how Swing works.
When you create a JFrame, Swing uses the OS widget for the frame. The title bar that you see is part of the OS component and you have no direct control over it with Swing. You can hide the titlebar (and border) of the frame by using setUndecorated(false) as suggested earlier. In this case you loose all the functionality associated with the title bar (dragging and access to all the buttons) and the Border (resizing). So if you need any of this functionality you need to recreate it all yourself.
On the other hand you can use:
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame frame = new JFrame();
and Swing will build a title bar and Border for you and add back all the default functionality. So if you want to prevent dragging you would now need to inspect the JFrame for all its components to find the component that represent the title bar. When you find this component you can then remove the MouseMotionListeners from the component to prevent dragging. This way the title bar will still be there and the buttons will be active, but the dragging will be disabled. I would guess that is easier the adding in all the functionality to an undecorated frame.
As you have already realized a JInternalFrame is a component completely written in Swing so you have access to the child components, which is essentially the approach I'm suggesting for the JFrame as well.
To remove the titlebar, use
setUndecorated(true);
You could then re-add buttons for maximize/minimize. The source for maximize-button could look something like that (just to get an idea). Use JFrame.ICONIFIED for minimize button.
JButton btnMaximize = new JButton("+");
btnMaximize.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
if(MainFrame.this.getExtendedState() == JFrame.MAXIMIZED_BOTH) {
MainFrame.this.setExtendedState(JFrame.NORMAL);
}
else {
MainFrame.this.setExtendedState(JFrame.MAXIMIZED_BOTH);
}
}
});
Take a look at this article - i think it is pretty much what you need for the JFrame part.
http://www.stupidjavatricks.com/?p=4
It is based on JDialog, but it should be pretty much the same as JFrame. Maximize/minimize should be pretty much the same as the close button.
For JInternalFrames...
javax.swing.plaf.InternalFrameUI ifu= this.getUI();
((javax.swing.plaf.basic.BasicInternalFrameUI)ifu).setNorthPane(null);
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.
I have a JPanel, which I would like to detect the following events
(1) When the mouse move in
(2) When the mouse move out
The (1) is quick easy. (2) is a bit tricky. Currently, I have to register event at all the components around JPanel. If the neighbor around JPanel detected a mouse move in event, this also means that JPanel is having (2) situation. However, this is a rather dirty away, as I add in new components in the future, this dirty workaround will break.
Another method is to have a timer to monitor the JPanel. If the mouse position is not within JPanel within x seconds, I can consider JPanel is having mouse move out event.
However, this seem a dirty way to me too, as having a separate timer to perform such common task is overkill.
Is there any better way, which Java platform may provide?
Have your class implement MouseListener and add it as a mouse listener on the outermost panel. You should get a mouse-entered event when the mouse moves over the panel, and mouse-exited when it leaves; regardless of whatever components the panel contains.
From the JavaDoc:
void mouseEntered(MouseEvent e)
Invoked when the mouse enters a component.
void mouseExited(MouseEvent e)
Invoked when the mouse exits a component.