I'm trying to code a level creator for my game in which you drag objects to their desired positions, but I'm having trouble figuring out whether or not the mouse button is being held down.
I'm using a MouseAdapter to listen for mouseClicked and mouseReleased events, but they seem to fire unpredictably. Usually, the program doesn't register either the mouse being clicked or released, but on occasion, one will be fired when it shouldn't be. A SOE will be thrown here and there, and eventually, they will be thrown repeatedly until the program is terminated. Any suggestions on working around this?
I think you're probably listening for the wrong events. MOUSE_CLICKED means MOUSE_PRESSED + MOUSE_RELEASED.
I think you probably want to be looking for MOUSE_PRESSED instead of clicked.
See the api for MouseEvent for more details: http://docs.oracle.com/javase/7/docs/api/java/awt/event/MouseEvent.html
Also, the MOUSE_DRAGGED event may be of some use to you.
Related
I am developing a Java Swing based video game. I am having a problem with detecting keystrokes- the 'A' (move left) and 'D' keys (move right), where it almost seems they are not firing (but happens rarely). Almost as if they have become unregistered. Now, I have setup log files to capture the keyboard events, and again one of the keyHandlers at some point does not fire. Now when this does happen, if I click into the main screen of the game with my mouse, the keyHandler that somehow got lost seems to work again. Almost as if the "Focus" was inadvertantly transferred to some other widget in the game.
Here is the code to setup the Action Maps:
topStatusPanel.getInputMap().put(KeyStroke.getKeyStroke("pressed A"),
"aCharKeyPressed");
topStatusPanel.getActionMap().put("aCharKeyPressed", aKeyActionPressed);
topStatusPanel.getInputMap().put(KeyStroke.getKeyStroke("released A"),
"aCharKeyReleased");
topStatusPanel.getActionMap().put("aCharKeyReleased", aKeyActionReleased);
topStatusPanel.getInputMap().put(KeyStroke.getKeyStroke("pressed D"),
"dCharKeyPressed");
topStatusPanel.getActionMap().put("dCharKeyPressed", dKeyActionPressed);
topStatusPanel.getInputMap().put(KeyStroke.getKeyStroke("released D"),
"dCharKeyReleased");
topStatusPanel.getActionMap().put("dCharKeyReleased", dKeyActionReleased);
MoveSubLeftActionStart aKeyActionPressed= new MoveSubLeftActionStart();
MoveSubLeftActionStop aKeyActionReleased= new MoveSubLeftActionStop();
MoveSubRightActionStart dKeyActionPressed= newMoveSubRightActionStart();
MoveSubRightActionStop dKeyActionReleased= new MoveSubRightActionStop();
Would really appreciate any ideas on this. Is there a way to force focus to a specific widget?- would I then for every other widget in the game have to set it to "unfocusable?" Could this be the issue? Appreciate any help here.
Here's an in-depth treatment on focus management and keyboard event handling.
If your JPanel contains other components, they might get the focus and not propagate the key events up the component chain.
http://docs.oracle.com/javase/6/docs/api/java/awt/doc-files/FocusSpec.html#RequestingFocus
I'm currently teaching myself LWJGL's mouse class, but there is something I still don't know how to do. I want to be able to handle double-click mouse events, but I don't know how.
It is not (AFAIK) natively supported. You have to do it yourself.
One way to do that : memorize the event date (System.curentTimeMS() or equivalent).
If the previous clic event was recent (~200 ms), it's a double-clic. else, simple clic.
Hope it helps...
I see there are methods already built for adding and removing mouse listeners, I suppose I could add them and remove them as needed. I just wasn't sure if there was a better way.
Having my JLabel respond to all mouse events over it but sometimes do nothing isn't quite what I'm looking for, it would be nice if my Labels had the mouse listener only when I needed it to. Maybe this whole idea is just a weird approach.
You register the Listener once and for all; you don't turn it off and on.
You can code logic inside to only take action under certain conditions of your choosing. As long as you make the information available that's needed for a decision your implementation should be fine.
I have a simple program that utilizes Java Swing Timer to display an image for 400 miliseconds, in this period of time I just want to stop all ActionListeners or stop taking ActionEvents. I've got 40+ buttons and want a simple way to do this.
Is there anyway to do that in Java?
Can you determine that you are in this "image displayed" state? The image goes up and you set the state to "image displayed" or whatever. Go through your widgets and decide which ones are supposed to be dead while the image is up. Turn them into Observers of this state value. When the state changes, they either enable or disable, as appropriate. The image code doesn't do anything directly to any widget. It just declares that the state is now "image displayed". It's up to the Observers to decide what to do, if anything, with that information.
Or use the GlassPane. That works too. Of course, the GlassPane shuts down everything. If you need to be more selective, you need a more fine-tuned approach.
You can use a temporary GlassPane instance to consume all events by registering empty listeners to it.
Use an undecorated modal JDialog to display the image. Before you make the dialog visible you would start a Timer. When the Timer fires in 400 ms you close the dialog.
I've had similar issues and typically found that its a design issue that got me in that situation. Being the case, I still had to find away around it. To fix the issue, I kept a list of the elements that I wanted to disable (stop listening) and iterated through them at the beginning and end of the timer. For buttons it should be as simple as:
for(Component c : listOfToggledComponents){
c.setEnabled(shouldItBeEnabled);
}
For buttons, this will grey out the button. Similar things happen to other swing components.
i've panel which contains a text field for entering number and a submit button
sometimes new (updated) value can not be sent when i click the button (the previous value of the field is sent)
in the debug mode, i see that sometimes
AbstractButton.fireActionPerformed()
is called (which gets the value of the field at that time and then submits) by event dispatch thread before
JFormattedTextFiled.FocusLostHandler
and
JFormattedTextField.commitEdit()
(which updates the value of the field).
i think jbutton event should have never been called before the text field loses the focus and updates its value
any idea about the problem?
i'm using xp-sp2 and java 1.6.0_06-b02
As far as I know, Java makes no guarantees about the order of events (someone please correct me if I am wrong!). In any case, problems with the focusLost event seem to be normal. We naturally expect it to be processed before the focus actually shifts and events for the new control are initiated. This is not the case.
As the post by Catalina Island implies, the solution is to use "invokeLater". The code for your "submit" button should look something like this:
protected void buttonClick() {
Runnable doStuff = new Runnable() {
public void run() {
// Do whatever button processing is needed here
}
};
// Invoke later, so that any LostFocus event will have been processed first
SwingUtilities.invokeLater(doListSelection);
}
If you have many controls that do some processing, and many controls that could be losing the focus, there seems to be no "nice" solution. Frankly, this is a weakness in Swing: it should guarantee a logical order of events during a change of focus.
Sorry, I have re-read your question - I have misunderstood it previously.
I cannot tell you why the focus is not moved from the field, but we had a similar issue in our application, but with the JTable and edits were not committed to the CellRender despite that we have set all required table properties. We just had to move focus away from the table cell as the first action in our event listener
thanks for replies guys and excuse me starting the same therad in java forum (i was not aware of the rules): http://forums.sun.com/thread.jspa?threadID=5445465&tstart=0
anyway, actually i'm interested in the cause of the problem rather than the solution
there are two cases in the EventQueue
here are the events for case 1:
MouseEvent (MOUSE_RELEASED)
MouseEvent (MOUSE_CLICKED)
InvocationEvent
InvocationEvent
InvocationEvent
CausedFocusEvent (FOCUS_LOST; opposite: JButton; source: FormattedNumberField)
CausedFocusEvent (FOCUS_GAINED; opposite: FormattedNumberField; source: JButton)
InvocationEvent
MouseEvent (MOUSE_MOVED)
MouseEvent (MOUSE_EXITED)
and here are the events for case 2:
CausedFocusEvent (FOCUS_LOST; opposite: JButton; source: FormattedNumberField)
CausedFocusEvent (FOCUS_GAINED; opposite: FormattedNumberField; source: JButton)
InvocationEvent
InvocationEvent
...
MouseEvent (MOUSE_RELEASED)
MouseEvent (MOUSE_CLICKED)
InvocationEvent
InvocationEvent
...
MouseEvent (MOUSE_MOVED)
MouseEvent (MOUSE_EXITED)
maybe java does not guarantee the order of the events. if it's true it would be a common problem but it's an unusual and very rare situation. even i can't reproduce this problem in other gui panels. i wonder what may cause this problem.
When I write an event handler that does something with the value of another component, I reference it directly. If your 'LostFocus' handler must run before the contents are valid, and if we can't guarantee it will have run before the button action has started, it might be a good idea to move the code contained within the 'LostFocus' handler into a private method that can be accessed by that handler and the button action, so it can do the work itself. When 'LostFocus' eventually fires, it will be executed again, but this shouldn't matter.
I'm pretty sure the the EventQueue keeps things sequential, but I've seen the debugger change the apparent order when I forget to use invokeLater() from another thread.