Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / GUI / October 2005

Tip: Looking for answers? Try searching our database.

focus events being received out of sequence

Thread view: 
Anup - 23 Sep 2005 18:15 GMT
I have a complicated applet where each component is registered with
multiple focus listeners. I have several pairs of JTextFields and
JButtons - textfield A, button A, textfield B, button B etc. Clicking
on a JButton normally causes a JTable to be popped and focus
transferred to it. Clicking on the table header or selecting a table
row causes the table popup to close and the focus transferred to the
textfield associated with the button.

I'm running into a strange case where the focus is initially on
textfield A. Clicking on button B causes a temporary loss of focus on
textfield A. The trace shows that the focus owner is null and the
permanent focus owner is textfield A. The table still gets launched.
Selecting a table row causes it to close but no component has focus any
more. Focus owner continues to be null, and permanent owner continues
to be textfield A.

After working on other windows in the meantime, and returning to this
window I find that the focus in now back to textfield B, as it should.
The trace shows that B has received permanent focus events. This is
followed by receiving permanent focusLost events on A and then
permanent focusGained events on A. At the point all in said and done,
the focus appears on B.

Does someone know why the focusGained event on B appears before focus
events on A? Another strange thing in the trace was that some focus
gain/loss method invocations were interrupted, another focus method
invoked and the previous method resumed. I could possibly take care of
this by using synchronized on all focus gain/loss methods. Also, some
methods show only part of execution and not even resumed. This is still
a mystery to me. I'll appreciate if someone can shed light on this.
Roedy Green - 24 Sep 2005 02:07 GMT
>Does someone know why the focusGained event on B appears before focus
>events on A? Another strange thing in the trace was that some focus
>gain/loss method invocations were interrupted, another focus method
>invoked and the previous method resumed.

you do realise you must not invoke swing methods from anything but the
Stwing event thread.  See http://mindprod.com/jgloss/threads.html
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

Anup - 02 Oct 2005 00:23 GMT
Roedy, I browsed the link on threads you provided. I liberally
sprinkled my code with println of
SwingUtilities.isEventDispatchThread() and
Thread.currentThread().getName().

I ran the compiled code under JBuilder as well as a signed applet in IE
browser. This is what I discovered:
1. In the initial bringup of the form, the main thread returned
isEventDispatchThread=false and thread name of main (JB) or class name
(IE). ActionPerformed methods returned the same results. FocusGained
and Lost returned isEventDispatchThread=true and thread name of
AWT-EventQueue-1 or AWT-EventQueue-3. I noticed the threads were
interfering with one another.
2. Once the form was up, all of the methods returned
isEventDispatchThread=true and the thread name was AWT-EventQueue-1 or
AWT-EventQueue-3. I noticed that AWT-EventQueue-1 threads interrupted
AWT-EventQueue-3 threads.

The questions I have for you are:
1. On the initial bringup of the form, why do focus gain and lost use
awt event queue threads but actionPerformed uses the main thread?
2. On the initial bringup, how can I force everything (main,
actionPerformed, focus gain/lost) to run under the same thread?
3. What determines which awt event queue thread focus gain and lost
will operate under since they are invoked asynchronously.

Anup
Roedy Green - 02 Oct 2005 04:53 GMT
>AWT-EventQueue-1 or AWT-EventQueue-3

What kind of machine are you running?  I don't think I have ever seen
more than one event queue thread, mind you it is not something I look
for regularly.  IIRC we debated whether the language spec would permit
more than one, and we decided yes.

Have you an "ordinary" machines e.g. Window/Linux desktop to try this
on?  If it works fine, and you see it has only  one event queue, that
is pretty good evidence the multiple event queues are the culprit.

I am gaping like a goldfish trying to think what the implications of
this are.  With multiple event threads how could Swing be thread safe
unless you do synchronisation even in your event handling code?  How
would anyone know to do that??  Help!!! This does not compute.

Is there any possibility you did some odd thing to spawn a new event
Thread?

Scan the JDK docs to see  if there is anything about multiple event
threads.

>The questions I have for you are:
>1. On the initial bringup of the form, why do focus gain and lost use
>awt event queue threads but actionPerformed uses the main thread?

I will first answer how, not why. My answer is only roughly correct.
There will be details wrong or simplified, but it will do for the
current purpose of giving you a rough internal model for predicting
its behaviour..

In beginning, there was just one Thread,  Everything was done on it.
Java not "know" whether you are going to do a console app, an AWT app
or a Swing app.  They are all the same when a app starts.  You build
GUI components in RAM. But they are just ordinary objects. They are
not visible. The OS knows nothing about them.  All is make-believe so
to speak-pure GUI simulation. Further there are no events yet.  At
some point you call showtime! formally known as JFrame.setVisible(
true ).  At this point Swing sets up a Thread to service the event
queue. The OS creates a peer or peers, and a picture appears on the
screen.  Mouse events and keyboard events start getting generated and
dispatched. All that happens with the SECOND thread.  Your mainline
code continues to use the main thread.  Usually it exits, leaving the
JFrame still visible. The SECOND thread keeps servicing events,
especially repaint events.  So from now on, you would expert anything
to run on the SECOND thread.  

Now  to answer your why question.  IIRC,  in the olden days of Java
1.0 there was only one thread, and it handled main and events.  It did
not start handling events UNTIL you called exit in main.  Others have
told me I just imagined this or read it from some ignoramus.  But
let's say for argument's sake that it DID work that way.  The problem
is your GUI would be unresponsive until you called exit.  Sometimes
your main has useful things to do.

>2. On the initial bringup, how can I force everything (main,
>actionPerformed, focus gain/lost) to run under the same thread?

There are basically two approaches:

1. spin off event handling code on the background thread..
2. spin off gui poking code on the event thread.

In any large Swing app you will do both.  See
http://mindprod.com/jgloss/thread.html SwingWorker for spinning off
lengthy event handlers on a private thread.

See http://mindprod.com/jgloss/SwingUtilities.invokeLater to spin of
background work onto the Event thread. ALL Swing component poking must
be done this way. You must never call a Swing method from anything but
the event thread, with a few exceptions listed in my essays on
threads.

>3. What determines which awt event queue thread focus gain and lost
>will operate under since they are invoked asynchronously.

This is where I am utterly baffled at this point.  I can't see how
Swing could possibly work with two event threads.  AWT yes, but not
Swing.

I hope someone else will chime in.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

Anup - 02 Oct 2005 21:01 GMT
> >AWT-EventQueue-1 or AWT-EventQueue-3
> Have you an "ordinary" machines e.g. Window/Linux desktop to try this
> on?  If it works fine, and you see it has only  one event queue, that
> is pretty good evidence the multiple event queues are the culprit.

Yes, I'm running on windows xp.

> I am gaping like a goldfish trying to think what the implications of
> this are.  With multiple event threads how could Swing be thread safe
[quoted text clipped - 3 lines]
> Is there any possibility you did some odd thing to spawn a new event
> Thread?

Yes, there is! The main thread starts another thread. But this doesn't
quite explain it, read further below.

> >2. On the initial bringup, how can I force everything (main,
> >actionPerformed, focus gain/lost) to run under the same thread?
[quoted text clipped - 3 lines]
> 1. spin off event handling code on the background thread..
> 2. spin off gui poking code on the event thread.

I tried the invokeLater method in the main thread and also the thread
it spawned off. The trace shows that immediately after getting control,
the invoked-to methods are running under the same awt event thread.

> >3. What determines which awt event queue thread focus gain and lost
> >will operate under since they are invoked asynchronously.
>
> This is where I am utterly baffled at this point.  I can't see how
> Swing could possibly work with two event threads.  AWT yes, but not
> Swing.

However, somewhere down the line I do see 2 awt event threads being
active with different priority, even after using invokeLater. I have
yet to do a detailed analysis of the trace to look for any
distinguishing features between the two.

Anup
Roedy Green - 03 Oct 2005 01:50 GMT
>Yes, there is! The main thread starts another thread. But this doesn't
>quite explain it, read further below.

I think I know what you did. This is subtle.

In your main thread, you can get away with poking GUI elements on the
main thread  before they capable of generating events, namely until
you first call pack or setVisible( true ).

From that point on, you must use SwingUtilities.invokeLater or invoke
them from the event processing thread.

The question arises, what triggers the creation of the AWT/Swing
thread?

I will conjecture it is when you call pack/setVisible from something
other than the Swing thread.

I think you did this TWICE, thus triggering two even processing
threads! which then proceeded to slash each other to death.

What we need now is a recipe to avoid this disaster.

I suspect there are two safe approaches.  Always use invokeLater when
not definitely on the even processing thread, or use it after the
first pack/setvisible.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

Roedy Green - 03 Oct 2005 04:30 GMT
>I suspect there are two safe approaches.  Always use invokeLater when
>not definitely on the even processing thread, or use it after the
>first pack/setvisible.

Oddly i discovered the answer in the Java glossary.  I am in the
process of separating out the Swing thread lore into its own entry.

Sun now recommends ALL Swing methods be called with invokeLater unless
triggred from the event thread, even during the initial construction.
They say you can leave old code as is, but all new code should follow
that technique.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

Roedy Green - 03 Oct 2005 02:06 GMT
>I tried the invokeLater method

The invokeLater method is defined as:

Causes doRun.run() to be executed asynchronously on the AWT event
dispatching thread.

Likely by some Bette Midler fan who set up the joke as carefully as
any in Airplane II.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

Anup - 03 Oct 2005 20:33 GMT
> > There are basically two approaches:
> >
[quoted text clipped - 4 lines]
> it spawned off. The trace shows that immediately after getting control,
> the invoked-to methods are running under the same awt event thread.

Let me elaborate. I renamed the init method of mainline to initSafe and
created a new init method to invokeLater initSafe. The trace shows
initSafe running under the awt event thread. Somewhere in the middle of
its execution, initSafe spawns off another thread to a class
FormFactory which is a subclass of Thread. I renamed the run method of
FormFactory to runSafe and created a new init method to invokeLater
runSafe. The trace shows runSafe running under the same awt event
thread as initSafe. So as soon as I get control in the mailine or the
spawned thread, I invokeLater to an awt event thread.

> > >3. What determines which awt event queue thread focus gain and lost
> > >will operate under since they are invoked asynchronously.
[quoted text clipped - 7 lines]
> yet to do a detailed analysis of the trace to look for any
> distinguishing features between the two.

Ok, I did the detailed analysis. Initially, all the events are being
serviced by awt event thread 1. Then for some reason, all the events
get serviced by awt event thread 3. Then they revert back to thread 1.
I know what I'm seeing but I don't know why.

Anup
Anup - 03 Oct 2005 23:44 GMT
> > However, somewhere down the line I do see 2 awt event threads being
> > active with different priority, even after using invokeLater. I have
[quoted text clipped - 5 lines]
> get serviced by awt event thread 3. Then they revert back to thread 1.
> I know what I'm seeing but I don't know why.

I did some more analysis. At the time one thread takes over from the
other, some strange behavior does take place. When the higher priority
thread took over, a caret was visible when it was not supposed to be.
When the lower priority thread took control back it seemed like it was
handling some events that were left over at the time the higher
priority thread had intervened. So the 2 threads seem to be playing a
part in the strange behavior I'm seeing. The trick is to get it down to
just one thread.

Anup
Roedy Green - 04 Oct 2005 10:49 GMT
>Ok, I did the detailed analysis. Initially, all the events are being
>serviced by awt event thread 1. Then for some reason, all the events
>get serviced by awt event thread 3. Then they revert back to thread 1.
>I know what I'm seeing but I don't know why.

We have to track down what is creating that bogus event thread.

Off the top of my head you need some code like this to tell you what
threads exist.

Thread[] allThreads =  new Thread[ Thread.activeCount()];
Thread.enumerate ( allThreads );
for (Thread t : allThreads )
{
System.out.println( t.getName() );
}

Pepper your code with this or something more sophisticated and see if
you can track down where that extra event thread is coming from.

I suspect it will be coming from a pack or setVisible(true ) not done
with invokeLater.  Check out main first, especially if you open two
frames, check the second.

See http://mindprod.com/jgloss/swingthreads.html
for background on the error you are trying to find.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

Roedy Green - 04 Oct 2005 11:22 GMT
>Thread[] allThreads =  new Thread[ Thread.activeCount()];
>Thread.enumerate ( allThreads );
[quoted text clipped - 5 lines]
>Pepper your code with this or something more sophisticated and see if
>you can track down where that extra event thread is coming from.

the sort of things you might do :

assert isOnlyOneEventThread(): new Throwable().printStackTrace();

if (Thread.activeCount() != prevActiveCount )
 {
 new Throwable().printStackTrace();
 dumpThreads();
 prevActiveCount = Thread.activeCount();
 }

of course you have to write boolean isOnlyOneEventThread
and dumpThreads
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

Anup - 04 Oct 2005 21:33 GMT
> >Thread[] allThreads =  new Thread[ Thread.activeCount()];
> >Thread.enumerate ( allThreads );
> >for (Thread t : allThreads )
> >{
> >System.out.println( t.getName() );
> >}

Roedy, you'll never believe this. I printed out all the threads as you
suggested. There are 2 thread groups - applet thread group and console
writer thread group, each having an awt event thread. Java made a
performance improvement to disallow blocking of console output by using
the console writer thread group. Trouble is, java also seems to use
this thread group for handling events. Just for experimentation, I set
the option for "do not start console". With this option, the multiple
caret situation disappeared. This is probably a java bug. In the
meantime, I'm wondering if there is any way to disable the console
writer thread group without disabling the console itself.

Anup
Roedy Green - 05 Oct 2005 00:11 GMT
>Roedy, you'll never believe this. I printed out all the threads as you
>suggested. There are 2 thread groups - applet thread group and console
>writer thread group,

With an Applet you have the problem all the different Applets can be
running at once and they must share a common console, merging their
outputs.  The console is not really a console it is GUI windows
something like a scrolling TextArea.

So it seems plausible it could have its own dispatch thread.  However
your Gui elements and your event handlers I would think would not have
anything to do with it. However, it is conceivable that keystrokes are
handed by it since your app could conceivably also field lines input
from the console.

This is turning into a major expedition.  We at least we are learning
something interesting each day.

So things to try:
1. convert your Applet to an application hybrid by adding a main
method.  See http://mindprod.com/jgloss/applet.html for how.
Run as an application to see if it behaves sanely.  If it does, think
if it will be possible to redeploy your app as a JAWS app.

2. Run your program as an Applet, and see WHICH event handlers get
which thread.  Is there any pattern?

3. Did you ever do a setVisible() or pack() on the console thread? It
is just as naughty as any other non-Swing thread.

Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.

Anup - 05 Oct 2005 12:59 GMT
> >Roedy, you'll never believe this. I printed out all the threads as you
> >suggested. There are 2 thread groups - applet thread group and console
> >writer thread group,

> So it seems plausible it could have its own dispatch thread.  However
> your Gui elements and your event handlers I would think would not have
> anything to do with it.

Theoretically, it shouldn't but the trace says otherwise.

> So things to try:
> 2. Run your program as an Applet, and see WHICH event handlers get
> which thread.  Is there any pattern?

It appears that the jvm started assigning events to the applet event
thread and at some point in time also started assigning them to the
console writer event thread (perhaps due to an overload?) regardless of
component or event handler method. Since the console writer thread was
at a higher priority, all of those events ran till exhausted before the
applet event thread could run again.

> 3. Did you ever do a setVisible() or pack() on the console thread? It
> is just as naughty as any other non-Swing thread.

I did nothing directly with the console thread. I didn't even know it
existed till the trace showed it.

Anup
Roedy Green - 05 Oct 2005 00:12 GMT
> In the
>meantime, I'm wondering if there is any way to disable the console
>writer thread group without disabling the console itself.

You could disable to console, but I don't see how it would co-ordinate
all the applets without its own thread.
Signature

Canadian Mind Products, Roedy Green.
http://mindprod.com Again taking new Java programming contracts.



Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.