Confusing Event Order in Java Swing Thread
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 s开发者_如何学运维ubmits) 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.
精彩评论