Login  Register

Re: KeyListener problem

Posted by Michael Schmid on Mar 19, 2020; 11:59am
URL: http://imagej.273.s1.nabble.com/KeyListener-problem-tp5023044p5023069.html

Hi Kenneth,

sorry, two corrections to what I had written:

(1) ImagePlus.show() waits for the image becoming visible in macros, but
not when called from Java. Nevertheless, imp.getWindow() should never
return null after imp.show(), except for BatchModeMacros.
See
   https://github.com/imagej/imagej1/blob/master/ij/ImagePlus.java#L490

It will happen, however, that the image does not become the foreground
image after imp.show(), so IJ.getImage() or
WindowManager.getCurrentImage() may still return a different ImagePlus
or null.

I do not see why window.setKeyListener(this)

(2) If it is possible that your plugin could be called from a macro
(e.g. from buttons of the ActionBar plugin) or a macro might be
executing while you plugin is used, you should NOT call ImagePlus.show()
from the EventQueue (e.g. from a key listener).
Also, in the EventQueue, don't wait until the image becomes visible;
this won't happen (such a code could cause ImageJ to hang).

So the safe strategy is to never call imp.show() in KeyListener
callbacks or the like. Rather have a separate thread with imp.show(),
retrieving the window and registering as KeyListener. Something like the
following:

public void keyTyped(KeyEvent e) {
    if (thisIsTheKeyForOpeningAnImage(e)) {
       Thread thread = new Thread(
          new Runnable() {
             public void run() {
                ImagePlus imp = ....
                imp.show();
                ImageWIndow win = imp.getWindow();
                win.setKeyListener(myPlugin.this);
             }
          },
       "windowOpenThread");
       thread.start();
    }
}
where myPlugin is your main class (implementing KeyListener).


What I can also recommend is placing all code in Listeners and new
threads in try{ ... } catch(Exception e) {IJ.handleException(e);}
blocks. Otherwise you won't notice whether there is an exception in
these methods (unless you start ImageJ from the command line with java
-jar ij.jar).

Michael
_______________________________________________


On 18/03/2020 6:07 pm, Michael Schmid wrote:

> Hi Kenneth,
>
> getting KeyListeners: There is method
>    KeyListener[] Component.getKeyListeners().
> Canvases, Containers (Windows, Panels), and gui elements (checkboxes,
> text fields, ...) are java.awt.Components.
>
> ImagePlus.show() should wait until the window appears, unless you call
> it from the EventQueue (e.g. from any Listener). Then you will
> experience a 2 sec delay, which is its timeout for waiting (if the image
> has not appeared yet in 2 sec).
> If you want to create the ImagePlus from the EventQueue, start a new
> Thread that creates it.
> After spawning the thread, I think you need a loop with maybe 10 msec
> delay waiting until the ImagePlus is shown (e.g. check for
> imp.getWindow() being non-null and win.isVisible() being true).
> If it is possible that your plugin will ever run in a macro, make sure
> that it also works in batchmode where no window will be displayed.
>
>
> Michael
> _____________________________________________________________
>
>
> On 18/03/2020 5:52 pm, Kenneth Sloan wrote:
>> No joy.  The improved(?) version exhibits the same problem.  Now on
>> two machines (but not yet on mine).  The symptoms are that no
>> KeyPresses are registered AT ALL.  Note that there is a call to IJ.log
>> at the start of keyPressed() - so this is not an issue with
>> wait/notify.  I'm glad I cleaned that up - but it wasn't the problem.
>>
>> It appears as if the KeyListeners are not being registered.  Is there
>> a way to  double check that a given class has been successfully
>> registered as a KeyListener?
>>
>> It also occurs to me that there might be a race condition here:
>>
>>     ipl.show();
>>     win = ipl.getWindow();
>>     canvas = win.getCanvas();
>>
>> Is it possible that  win and canvas may not yet be set, because
>> ipl.show() takes some time to complete?  Should I add something like
>> "wait(1000)" after the ipl.show()"?  Is there a direct way to check
>> that ipl.show() has finished all of its work before proceeding?
>>
>> For example...will this help?
>>
>>          ...
>>     ipl.show();
>>     ImageWindow win = null;
>>          while(null == win) {win = ipl.getWindow();}
>>     ...
>>
>> --
>> Kenneth Sloan
>> [hidden email]
>> Vision is the art of seeing what is invisible to others.
>>
>> --
>> ImageJ mailing list: http://imagej.nih.gov/ij/list.html
>>

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html