Confusing Event Order in Java Swing Thread - java

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.

Related

Java Swing: How to distinguish events triggered by user?

I'd like to update GUI elements (JComboBox, JLabel, etc.) from code which shouldn't trigger change event. Is it possible to find out from java.awt.event.ActionEvent or java.awt.event.ItemEvent if the change was caused by an user or by running code like this?
combo.setSelectedItem("my item")
The answer is: no.
But in some cases you can try to analyze the current InputEvent. To get it, use EventQueue.getCurrentEvent(). For example if user has triggered the change on clicking of another component, you can compare the component of the input event and the component of the action event (OK I know: it's unsafe. But in some cases it can help to avoid incrementing of application complexity).
For a button you can get the event modifiers:
int buttonModifiers = evt.getModifiers();
If the button event was generated with a call to doClick() the modifier is 0, otherwise not.
By the way, you can find out such differences relatively easy by logging / printing using evt.toString()
.

Cursor blinks in two fields (JTextField)

Hello? anyone had a problem like: cursor blinking in more than one field at a time?
In my case the following happens: When you double click on a field JTextField, opens a JDialog, so
after closing this, the focus is directed back to the field clicked before opening the screen.
What happens is that after performing this action, two fields are flashing at the same time (usually the first field
screen, as well as the field in which efetuei double click).
This medium is random, there are cases in which it does not occur.
When debugging the inner class Handler, contained within the class DefaultCaret more specifically the actionPerformed method, realized
that: time is a field, and time is another, which are precisely the fields that are flashing (q seems obvious I know). but they are
the own inner classes of Java that are calling the method.
When passing over the field using the Tab, the cursor false, vanishes.
I'm using JDK 6
I returned the focus within the invokeLater(), but not solved. Now both synchronized flash
The first JComponent focusable is one of the fields that flashing improperly
I'm using my own FocusTraversalPolicy, does that may be influencing? The funny thing is that there is no treatment particularly strange about my class.
I noticed that the standard Java class, using a method within the Syncronized getFirstComponent(), but added the same control, but still is not ok
Actually it's Focus issue for me.
Normally when JTextComponent looses Focus setCaretVisible(false) / setSelectionVisible(false) is called and when Focus gained opposite thing happens.
After closing JDialog try to return Focus inside invokeLater(). Also check what's the first focusable JComponent in the JDialog's parent.
This situation occurs because the project I'm developing is quite large, so do not get small examples of implementation
The project has many components, Tables and Container's, which require focus through at the same time.
It turns out that Swing, put in a queue for execution, a lot of threads, and then dispatching them going, and while he did not finish running it, you can cram grabFocus() or requestFocus(), which does not cry, the first he has to finish everything and then run my request focus.
Resolved palliatively this situation, using the Swing SwingUtilities.invokeLater(...);
Thanks for the tips.

GWT: How to put event in queue (equivalent to Swing invokeLater())?

Having the following szenario: blurring a textBox (input) writes text to my status-Box (in certain conditions), and clicking a button also writes text to the status-Box.
Now when clicking the button it will blur my textBox if it is focused and that will cause the status-Box to flicker as first the blurHandler will write its result and then the clickHandler.
As i want the result of the clickHandler to appear my idea is to let the blurHandler place an event at the end of the queue which checks whether a clickHandler has written a result before.
In Swing I would try SwingUtilities.invokeLater(Runnable).
The equivalent in GWT is said to be the Scheduler but those deferred or finally commands seems always to run after the current event and before the next.
So far i use Scheduler.scheduleFixedDelay with 100ms delay and hope it comes after the clickHanlder in each browser.
See similar problem with answer.
I think there must be a better solution for this.
How to really add an event to the end of the queue or is it impossible due to limitations of HTML?
Try:
Scheduler.get().scheduleDeferred(new Command() {
#Override
public void execute() {
.......
}
});
See
Class Scheduler

Should swing event handlers be queued after the event on the EDT?

Should swing event handling code be queued after the event on the EDT? If so, is it the responsibility of the event source to schedule the event handlers, or is it the responsibility of the event handler to schedule the actual handling code later?
Consider:
JButton b = new JButton();
b.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
/*
* SNIP 1
* do something that may affect other
* components or generate new events...
*/
// SNIP 2
EventQueue.invokeLater(new Runnable(){
public void run(){
/*
* do something that may affect other
* components or generate new events...
*/
}
});
}
});
SNIP 1 runs handler code when the event is received. If the JButton takes responsibility for scheduling event by EventQueue.invokeLater(), then this is probably correct. SNIP 2 receives the event, and takes responsibility of scheduling handler code after the event is received (and handled by all other listeners for this specific event type). Which is correct?
EDIT: Just for clarity, I want to schedule event handlers later on EDT because changing state in the first event handler may hide original state at the time of the event from other event handlers for the component.
Please let me know though if I am misunderstanding your question, but all code in the Swing event Listeners is by run on the EDT, so there is no need to queue anything on to the EDT. I have only rarely seen code such as in snip2 used in a Swing listener, and usually that's if the listener calls an anonymous inner Runnable in a background thread.
As #HFOE notes, elements in the EventQueue are sequential and ordered; SNIP 2 shouldn't be required. If I understand your requirement, one approach might be to forward the event to any other interested listener(s), as suggested in this question & answer.
I know its probably bad form to answer my own question, but I've come to the conclusion that one should queue event handlers after an event in Swing. The reason is this: each component can have more than one listener of a given type. You don't know what listeners are listening on any given component (swing itself may add listeners that you are unaware of), and you don't know what assumptions they make about the component tree, and the state of the tree when they handle an event.
Now, because each component can have multiple event handler for a certain event type, we don't know which event handler will be invoked first. If my event handler modifies the component tree, a subsequent event handler for the same event type will not see the component tree as it was at the time of the event. Instead, it will see the component tree as it was after my changes. The same problem exists for other application state which may be inspected and modified by two separate listeners of the same type on the same component. This is surely not right.
Secondly, there is a concept of events being dispatched by the EDT in a sequential order. ie. If event x happened before event y in real time, then the event handlers for x should run before the event handlers for y. Now, if my component, lets call it c1, has 2 event handlers for event actionPerformed() - eh1 and eh2. When actionPerformed() is fired on c1, eh1 is invoked to handle the event. It then modifies component c2, and causes a itemStateChanged() event to be fired on c2. Because this change queued after the first actionPerformed() event was complete (later on the EDT), and because c2 does not queue the itemStateChanged() event to run later on the EDT, the itemStateChanged() event is handled by all its listeners. Only then does the second actionPerformed() listener (eh2) get to handle the original actionPerformed() event.
If eh2 was also a listener to itemStateChanged() events on component c2, then it would appear to eh2 that the itemStateChanged() event actually happened before the actionPerformed() event. This too is surely not right.
So that answers question 1. Yes, event handling code, which modifies application state or the component tree should be scheduled for execution after the event is processed. The event handlers should inspect whatever state they need to inspect at the time of the event, but react to the event (make changes) later on the EDT, by calling EventQueue.invokeLater().
The second part of my question is about whose responsibility it is to ensure that handling of events happens after the event itself has taken place. In hindsight, this is a stupid question. The same problem exists if the event handlers are executed immediately when an event occurs, or if they are executed later by the component calling EventQueue.invokeLater().
Incidentally, while I was researching this, I saw that not all Swing component do this uniformly. For example, JCheckBox fires the itemStateChanged() events immediately when the event occurs, while JComponent fires componentResized() (via is super class java.awt.Component) later on the EDT.
So it seems that the most robust way to handle events is to first inspect your state to make decisions about what actions you will take, then perform those actions later on the EDT. Any thoughts? I'd love to hear other people's insight into this.

action listeners and event sources in Swing

OK, so if I add an ActionListener to a GUI element, and it's the only element I use that ActionListener with, does it matter which of the following lines (a,b) I use to get the checkbox selected state?
final JCheckBox checkbox = (JCheckBox)this.buildResult.get("cbDebugTick");
checkbox.addActionListener(new ActionListener() {
#Override public void actionPerformed(ActionEvent event){
boolean bChecked =
// (a) checkbox.isSelected();
// (b) ((JCheckBox)event.getSource()).isSelected();
model.setPrintDebugOn(bChecked);
}
});
It makes sense to me that if I add the ActionListener object to multiple GUI elements, then I should use (b).
And in (b), is it OK to blindly cast event.getSource() to JCheckBox, since I'm the one who added the action listener, or should I program defensively and do an instanceof check?
note: this question is in the context of event listeners in general; kdgregory has some good points below specifically re: checkboxes which I had neglected to consider.
I'd do neither.
If clicking the checkbox is going to start some action, I'd attach an ItemListener, then just look at the selection state in the ItemEvent.
However, checkboxes don't normally invoke actions, they manage state. So a better approach is to examine all of your checkboxes in response to whatever does kick off the action.
Edit: some commentary about the larger issues that the OP raised.
First, it's important to realize that large parts of Swing represent implementation convenience rather than a coherent behavior model. JCheckBox and JButton have nothing in common other than the fact that clicking within their space is meaningful. However, they both inherit from AbstractButton, which provides implementation details such as the button's label. It also assumes that buttons are "pressed", and that pressing a button will initiate some meaningful behavior (the action). In the case of JCheckbox, however, the button press is not important, the change in state is. That state change is signaled to the ItemListener -- which is also defined on AbstractButton even though state changes are meaningless to other button types (the JavaDoc even says "checkbox").
One of the things that Swing did get right -- if hard to use -- is the idea of that an Action is separate from the control initiating that action. An Action object can be invoked from multiple controls: a menu item, a pushbutton on a dialog, a keystroke, whatever. More important from a design perspective is that it takes you away from the idea of a generic "listener" that tries to figure out what needs to happen. I've seen apps where a single listener receives input from the entire menu system, for example, and then runs through a big if/else chain to figure out which menu item was pressed. Using Actions means you have more classes, but in the long run gives you a more maintainable app.
Finally, from a usability perspective, there's a difference between controls that maintain state, such as JCheckbox and JTextArea, and those that initiate actions, such as JButton and JMenuItem. I have seen a (web) app where clicking on a radio button takes you to a different page. That's bad. Even if you're planning to use listeners internally, to update the state of some model, you should ask yourself why the collection of GUI elements do not in themselves provide you with a model.
For the case where the listener is exclusive (such as an anon listener), I use (a).
If the listener will be reused (eg, this is an instance of ActionListener) I'll write it as:
#Override
public void actionPerformed(ActionEvent event) {
Object src = event.getSource();
if (src == checkbox) {
boolean bChecked = checkbox.isSelected();
// ...
}
}
If you have several checkboxes and they are processed the same way, then instanceof makes sense.
in (b) to be rigourous, you should indeed do a instanceof check, but it's not that important. I would think both these lines are fine and acceptable, though (b) would be "better code"
Although, what is usually done in an action listener is simply call another method customized to your checkbox. So it would look like something like this:
#Override public void actionPerformed(ActionEvent event) {
//your treatment would be in this method, where it would be acceptable to use (a)
onCheckBoxActionPerformed(event)
}
I'd program with b defensively as it's the best-practice option. But if only you are ever going to use the code then there is no reason why you can't do a. However, imagine how happy you will be with yourself if you come back to it at some future point, change something and find you wrote good code which you can directly reuse...

Categories