KeyListener problem

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
14 messages Options
Reply | Threaded
Open this post in threaded view
|

KeyListener problem

Kenneth Sloan-2
I have a plugin which displays an image, removes IJ.instance Key and Image Listeners, adds itself as Key and ImageListener, and handles keypresses for the keys 1-6.  

It works perfectly on my machine (a mac, latest OS) - but fails on someone elses - INTERMITTENTLY.

When it fails, the plugin reports removing and adding the appropriate listeners...and then never reports seeing ANY keypress. (keyPressed() is never called).

I followed the template in keyListener.java (I think that's the right name).

There is a requestFocus() in what I think is the right place, and I've asked the "client" to be sure the image window is on top and "selected".  No joy.

I'm stumped - does anyone have any experience with similar problems?  Any suggestions on how to proceed?  Recall that I can't reproduce the problem on my machine.  My "client" reports that the plugin sometimes works - perhaps several times in a row - and then fails.  Once it starts to fail, even restarting FIJI does not revive it.  I'm guessing (but have not asked) that it requires a reboot to fix.

Any clues?
--
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
Reply | Threaded
Open this post in threaded view
|

Re: KeyListener problem

L'assegnista
Dear Kenneth,
I've run in a similar problem with a python Macro I wrote for TrakEM2  with
the precious help of Albert Cardona.
http://imagej.1557.x6.nabble.com/Adding-keyboard-shortcut-to-toggle-visibility-of-patches-in-TrakEM2-td5016099.html

This macro sometimes behave exactly as you described, stopping working
randomly. In our case however, re-running the macro is sufficient to make
it work again. Back in 2016 we also had to open a new display, the instance
to which the KeyListener is bound, but this magically resolved at some
point. Moreover, lately this strange behaviour is very rare and we are
indeed successfully using it.

Here the final code, multiple keys are specified with subsequent elif

from java.awt.event import KeyEvent, KeyAdapter
from ini.trakem2.display import Display, Patch

shortCut1="GFP"

class MyKeyListener(KeyAdapter):
         def keyPressed(self, event):
                keyCode = event.getKeyCode()
                     if KeyEvent.VK_1 == keyCode:
                          for layer in
Display.getFront().getLayerSet().getLayers():
                               patches = layer.getDisplayables(Patch)
                               for patch in patches:
                                    if shortCut1 in patch.title:
                                        if patch.visible == True:
                                               patch.visible = False
                                        else:
                                               patch.visible = True

Display.getFront().getCanvas().addKeyListener(MyKeyListener())

Hope this helps

Federico



Il giorno mer 18 mar 2020 alle ore 02:20 Kenneth Sloan <
[hidden email]> ha scritto:

> I have a plugin which displays an image, removes IJ.instance Key and Image
> Listeners, adds itself as Key and ImageListener, and handles keypresses for
> the keys 1-6.
>
> It works perfectly on my machine (a mac, latest OS) - but fails on someone
> elses - INTERMITTENTLY.
>
> When it fails, the plugin reports removing and adding the appropriate
> listeners...and then never reports seeing ANY keypress. (keyPressed() is
> never called).
>
> I followed the template in keyListener.java (I think that's the right
> name).
>
> There is a requestFocus() in what I think is the right place, and I've
> asked the "client" to be sure the image window is on top and "selected".
> No joy.
>
> I'm stumped - does anyone have any experience with similar problems?  Any
> suggestions on how to proceed?  Recall that I can't reproduce the problem
> on my machine.  My "client" reports that the plugin sometimes works -
> perhaps several times in a row - and then fails.  Once it starts to fail,
> even restarting FIJI does not revive it.  I'm guessing (but have not asked)
> that it requires a reboot to fix.
>
> Any clues?
> --
> 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
>


--
Federico Luzzati, PhD
Assistant Professor
University of Turin,
Dept. LIfe Sciences and Systems Biology (DBIOS)
Via Accademia Albertina, 13 - 10123 Torino - IT

Researcher at
Neuroscience Institute Cavalieri Ottolenghi (NICO)
Regione Gonzole, 10 - 10043 Orbassano (To) - IT

tel. +39-0116704683/ -6631
http://www.nico.ottolenghi.unito.it/index.php/it/adult-neurogenesis

Sostieni con il tuo 5xmille il NICO e la ricerca sulle malattie
neurodegenerative
Firma nel riquadro "Finanziamento della ricerca scientifica e
dell'Università"
CF 97564560015

--
ImageJ mailing list: http://imagej.nih.gov/ij/list.html
Reply | Threaded
Open this post in threaded view
|

Re: KeyListener problem

Kenneth Sloan-2
This is a JAVA plugin.  It's too big to post all of it - but here are what I think are the relevant parts.  Again - it works perfectly on one machine - and fails intermittently on another.

Perhaps someone who has done this before can spot my error.  I was following the template for keyListener on the imageJ site.


public class AVL_Area_Fraction implements PlugIn, KeyListener, ImageListener
{
...
    private boolean waitingForKey = false;    
    private int keyCode;
    private char keyChar;
    private int modifiers;
    @Override
        public void keyTyped(KeyEvent e) {}
    @Override
        public void keyReleased(KeyEvent e) {}
    @Override
        public void keyPressed(KeyEvent e)
    {
        IJ.log("keyPressed");
        if(!waitingForKey) return; // ignore keyboard when we don't want a key
        keyCode = e.getKeyCode();
        keyChar = e.getKeyChar();
        modifiers = e.getModifiers();
        IJ.log("   "+keyCode+"   "+keyChar+"   "+modifiers);
        waitingForKey = false;
    }
     
    @Override
    public void imageClosed(ImagePlus imp)
    {
        IJ.log("imageClosed");
        if(null!=win) win.removeKeyListener(this);
        if(null!=canvas) canvas.removeKeyListener(this);
        ImagePlus.removeImageListener(this);
        IJ.log("removed Listeners");
    }
    @Override
    public void imageOpened(ImagePlus imp){}
    @Override
    public void imageUpdated(ImagePlus imp){}
    @Override
        public void run(String arg0)
    {
... other setup
        // listen to keyboard - stop IJ from listening!
        win.removeKeyListener(IJ.getInstance());
        canvas.removeKeyListener(IJ.getInstance());
        IJ.log("removed IJ Listeners");
        win.addKeyListener(this);
        canvas.addKeyListener(this);
        ImagePlus.addImageListener(this);
        IJ.log("added Listeners");
...

                int category;
                try
                    {
                        win.requestFocus();
                        IJ.log("sampling...");
                        category = sampleAt(...);
                        IJ.log("sampled");
                    }
                catch (Exception e)
                    {
                        throw new RuntimeException(programName+" interrupted");
                    }
 ...
        // done listening to the keyboard
        win.removeKeyListener(this);
        canvas.removeKeyListener(this);
        ImagePlus.removeImageListener(this);
        IJ.log("removed Listeners");
...

   private int sampleAt(...)
        throws InterruptedException
    {
      ...
        while(true)
            {
                waitingForKey = true;
                while(waitingForKey) Thread.sleep(100);
                   
                // key pressed!
                // keyCode, keyChar, and modifiers are current
                if(keyCode == KeyEvent.VK_SPACE) return -1; // DELETE does not work
                if(keyCode == KeyEvent.VK_ENTER) return -2; // no mas!
                int category = keyCode - KeyEvent.VK_1; // 1-based keys; 0-based category
                if(category < 0) continue; // try again!
                if(category >= choices.length) continue; // try again!
                return category; // good category!
            }
    }
}



Looking at this, I'm wondering if there might be a race condition between adding the Listeners and going into the busy wait for "waitingForKey" to become false.  But...that doesn't look like an issue - so I'm just at a loss.  

When this fails, the log window shows

============================
removed IJ Listeners
added Listeners
sampling...
============================

So, it's clearly (?) stuck in the wait loop, and keyPressed is never called.

If anyone is up for it, I'd be happy to send the entire plugin for testing.

Again - works perfectly on one machine and fails intermittently on another.  Both mac laptops - the failing one is older than the one that works.  I think the "client" is currently testing on a 3rd laptop to see if the problem is specific to that one machine.

--
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
Reply | Threaded
Open this post in threaded view
|

Re: KeyListener problem

Michael Schmid
Hi Kenneth,

a few thoughts:

If you suspect a race condition between ImageListener and KeyListener,
can you try with the ImageJ daily build?
Since a few days, the ImageListener callbacks are in the EventQueue.
KeyListener callbacks are in the EventQueue anyhow.  So a race condition
between these callbacks cannot happen with the daily build.

By the way, after you are done, don't forget to register ImageJ as a
KeyListener again.

Instead of an endless loop for waiting, it would be nicer to use the
Java 'wait' and 'notify' mechanism (both must be in 'synchronized'
blocks).  There is an example in the PlotWindow class:

https://github.com/imagej/imagej1/blob/master/ij/gui/PlotWindow.java#L836
https://github.com/imagej/imagej1/blob/master/ij/gui/PlotWindow.java#L865


In your code with the endless loop, it would be better to declare
'waitingForKey' volatile or have an AtomicBoolean for it.  Otherwise, if
the threads running the keyListener callback (the EventQueue) and the
one running the endless loop are on different CPU cores, the one running
the event queue may have the "waitingForKey" variable in its own CPU
cache and it may go undetected that another core modifies it.  So the
statement
 > waitingForKey = true;
 > while(waitingForKey) Thread.sleep(100);
might actually behave like this:
 > while(true) Thread.sleep(100);

If you use the synchronized notify/wait mechanism instead, there is no
need for declaring variables as volatile because synchronized blocks
also care about the cache problem.

Michael
______________________________________________________________________

On 18/03/2020 2:17 pm, Kenneth Sloan wrote:

> This is a JAVA plugin.  It's too big to post all of it - but here are what I think are the relevant parts.  Again - it works perfectly on one machine - and fails intermittently on another.
>
> Perhaps someone who has done this before can spot my error.  I was following the template for keyListener on the imageJ site.
>
>
> public class AVL_Area_Fraction implements PlugIn, KeyListener, ImageListener
> {
> ...
>      private boolean waitingForKey = false;
>      private int keyCode;
>      private char keyChar;
>      private int modifiers;
>      @Override
> public void keyTyped(KeyEvent e) {}
>      @Override
> public void keyReleased(KeyEvent e) {}
>      @Override
> public void keyPressed(KeyEvent e)
>      {
> IJ.log("keyPressed");
> if(!waitingForKey) return; // ignore keyboard when we don't want a key
> keyCode = e.getKeyCode();
> keyChar = e.getKeyChar();
> modifiers = e.getModifiers();
> IJ.log("   "+keyCode+"   "+keyChar+"   "+modifiers);
> waitingForKey = false;
>      }
>        
>      @Override
>      public void imageClosed(ImagePlus imp)
>      {
> IJ.log("imageClosed");
> if(null!=win) win.removeKeyListener(this);
> if(null!=canvas) canvas.removeKeyListener(this);
> ImagePlus.removeImageListener(this);
> IJ.log("removed Listeners");
>      }
>      @Override
>      public void imageOpened(ImagePlus imp){}
>      @Override
>      public void imageUpdated(ImagePlus imp){}
>      @Override
> public void run(String arg0)
>      {
> ... other setup
> // listen to keyboard - stop IJ from listening!
> win.removeKeyListener(IJ.getInstance());
> canvas.removeKeyListener(IJ.getInstance());
> IJ.log("removed IJ Listeners");
> win.addKeyListener(this);
> canvas.addKeyListener(this);
> ImagePlus.addImageListener(this);
> IJ.log("added Listeners");
> ...
>
> int category;
> try
>    {
> win.requestFocus();
> IJ.log("sampling...");
> category = sampleAt(...);
> IJ.log("sampled");
>    }
> catch (Exception e)
>    {
> throw new RuntimeException(programName+" interrupted");
>    }
>   ...
> // done listening to the keyboard
> win.removeKeyListener(this);
> canvas.removeKeyListener(this);
> ImagePlus.removeImageListener(this);
> IJ.log("removed Listeners");
> ...
>
>     private int sampleAt(...)
> throws InterruptedException
>      {
>        ...
> while(true)
>    {
> waitingForKey = true;
> while(waitingForKey) Thread.sleep(100);
>
> // key pressed!
> // keyCode, keyChar, and modifiers are current
> if(keyCode == KeyEvent.VK_SPACE) return -1; // DELETE does not work
> if(keyCode == KeyEvent.VK_ENTER) return -2; // no mas!
> int category = keyCode - KeyEvent.VK_1; // 1-based keys; 0-based category
> if(category < 0) continue; // try again!
> if(category >= choices.length) continue; // try again!
> return category; // good category!
>    }
>      }
> }
>
>
>
> Looking at this, I'm wondering if there might be a race condition between adding the Listeners and going into the busy wait for "waitingForKey" to become false.  But...that doesn't look like an issue - so I'm just at a loss.
>
> When this fails, the log window shows
>
> ============================
> removed IJ Listeners
> added Listeners
> sampling...
> ============================
>
> So, it's clearly (?) stuck in the wait loop, and keyPressed is never called.
>
> If anyone is up for it, I'd be happy to send the entire plugin for testing.
>
> Again - works perfectly on one machine and fails intermittently on another.  Both mac laptops - the failing one is older than the one that works.  I think the "client" is currently testing on a 3rd laptop to see if the problem is specific to that one machine.
>
> --
> 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
Reply | Threaded
Open this post in threaded view
|

Re: KeyListener problem

Kenneth Sloan-2
Michael-

Thanks - I was trying to keep it simple, and failed.  I suspect that the multi-core issue is the correct answer.  I'll work on it.

Thank you for the prompt reply.

--
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
Reply | Threaded
Open this post in threaded view
|

Re: KeyListener problem

Kenneth Sloan-2
In reply to this post by Michael Schmid
Thank you!

I made the following changes:
...
   @Override
        public void keyPressed(KeyEvent e)
    {
        IJ.log("keyPressed");
        keyCode = e.getKeyCode();
        keyChar = e.getKeyChar();
        modifiers = e.getModifiers();
        IJ.log("   "+keyCode+"   "+keyChar+"   "+modifiers);
        synchronized(this)
            {
                IJ.log("notifying");
                notify();
                IJ.log("notified");
            }
    }
...

        while(true)
            {
                synchronized(this)
                    {
                        IJ.log("waiting...");
                        wait(); // keyPressed wakes us
                        IJ.log("woken up!");
                    }
                // key pressed!
...

and it's fine (on my machine...which is less than informative, but at least I didn't break anything).  Shipping now for the "client" to test.

Again - thank you for the prompt and useful reply.
--
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
Reply | Threaded
Open this post in threaded view
|

Re: KeyListener problem

Kenneth Sloan-2
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
Reply | Threaded
Open this post in threaded view
|

Re: KeyListener problem

Michael Schmid
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
Reply | Threaded
Open this post in threaded view
|

Re: KeyListener problem

Kenneth Sloan-2
I have solved the potential race condition by moving the:

        win = ipl.getWindow()

until AFTER several other interactions take place, all of which cannot proceed until the window is visible.  But, this has zero effect on my machine.

Another possibility was that the desired window had lost focus - but in that case (i.e., when I do it intentionally) pressing most number keys in 1-6 will invoke  some standard ImageJ shortcut,  and my "client" reports that "nothing happens" on those keypresses.

He has a new version, and if that fails I will go to watch it fail, in person.  I still can't reproduce it on my machine.

The good news is that I'm cleaning up a lot of cruft by eliminating all the possible problems.  None of them have helped, but the code is cleaner...

A nagging thought is that the plugin often works 1-4 times in a row on his machine and then fails.  Once it fails, it fails forever.  Even restarting  FIJI seems to have no effect - but re-instaling the plugin does (for at least the first invocation following installation).

Very strange!

If there are any volunteers, I can put  source code on Box and send a link (or just e-mail the source code.  It's 1 .java file (467 lines) and (in my opinion) very simple.  I'll accept all "pointing and giggling" at my bad coding style.  All it does is implement a standard stereology grid, displaying cross-hairs (using overlays) and asking the user to classify each point by typing a number from 1-6.  It really shouldn't be this difficult!

The hardest problem with intermittent bugs is replicating them!

--
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
Reply | Threaded
Open this post in threaded view
|

Re: KeyListener problem

Fred Damen
Greetings,

The plugin below seems to work for me. Closing the image window restores
the key handling back to normal.

Note that, in my interpretation of the javadocs for KeyListener,
uncommenting the restoration of the ij KeyListener should work the same by
including the e.consume() in the callbacks, but alas on the window machine
that I am currently on it does not seem to work the same.

Does the java virtual machine close down? If it actually has you should
not see what you are seeing.  FIJI may have closed or only seem to have
closed down, but the JVM might be keeping a handle on your objects for
some reason.  I had the problem ages ago, that a previous version of my
plugin was run every time I freshly compiled and ran an updated version of
the plugin.

Also try and send the JVM a SIGKILL (ctrl-\) and stare at the output...
(see previous emails on this subject)

Enjoy,

Fred

import ij.*;
import ij.process.*;
import ij.gui.*;
import java.awt.*;
import java.awt.event.*;
import ij.plugin.*;
import ij.plugin.frame.*;

public class My_Keys implements PlugIn, KeyListener, WindowListener {

   public void run(String arg) {
      ImagePlus imp = IJ.getImage();
      imp.getWindow().getCanvas().removeKeyListener(IJ.getInstance());
      imp.getWindow().getCanvas().addKeyListener(this);
      //imp.getWindow().getCanvas().addKeyListener(IJ.getInstance());
      imp.getWindow().getCanvas().requestFocus();
      imp.getWindow().addWindowListener(this);
      IJ.log("stealing keys for '"+imp.getTitle()+"'");
      }

    public synchronized void keyPressed(KeyEvent e) {
       IJ.log("Pressed: '"+e.getKeyText(e.getKeyCode()));
       e.consume();
       }

    public void keyTyped(KeyEvent e) {
       IJ.log("Typed: '"+e.getKeyText(e.getKeyCode()));
       e.consume();
       }
    public void keyReleased(KeyEvent e) {
       IJ.log("Releas11red: '"+e.getKeyText(e.getKeyCode()));
       e.consume();
       }

    public void windowActivated(WindowEvent e)   {}
    public void windowClosed(WindowEvent e)      { IJ.log("Bye"); }
    public void windowClosing(WindowEvent e)     { IJ.log("Leaving so
soon."); }
    public void windowDeactivated(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowIconified(WindowEvent e)   {}
    public void windowOpened(WindowEvent e)      {}
}



On Wed, March 18, 2020 1:16 pm, Kenneth Sloan wrote:

> I have solved the potential race condition by moving the:
>
> win = ipl.getWindow()
>
> until AFTER several other interactions take place, all of which cannot
> proceed until the window is visible.  But, this has zero effect on my
> machine.
>
> Another possibility was that the desired window had lost focus - but in
> that case (i.e., when I do it intentionally) pressing most number keys in
> 1-6 will invoke  some standard ImageJ shortcut,  and my "client" reports
> that "nothing happens" on those keypresses.
>
> He has a new version, and if that fails I will go to watch it fail, in
> person.  I still can't reproduce it on my machine.
>
> The good news is that I'm cleaning up a lot of cruft by eliminating all
> the possible problems.  None of them have helped, but the code is
> cleaner...
>
> A nagging thought is that the plugin often works 1-4 times in a row on his
> machine and then fails.  Once it fails, it fails forever.  Even restarting
>  FIJI seems to have no effect - but re-instaling the plugin does (for at
> least the first invocation following installation).
>
> Very strange!
>
> If there are any volunteers, I can put  source code on Box and send a link
> (or just e-mail the source code.  It's 1 .java file (467 lines) and (in my
> opinion) very simple.  I'll accept all "pointing and giggling" at my bad
> coding style.  All it does is implement a standard stereology grid,
> displaying cross-hairs (using overlays) and asking the user to classify
> each point by typing a number from 1-6.  It really shouldn't be this
> difficult!
>
> The hardest problem with intermittent bugs is replicating them!
>
> --
> 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
Reply | Threaded
Open this post in threaded view
|

Re: KeyListener problem

Kenneth Sloan-2
yes, well..my code is very similar, and works perfectly on my machine.

the problem is that it does NOT work on at least one other machine.

Latest complication: it seems to matter if the image file is read from an external hard drive (on a third machine - not mine).  It displays the image and goes through all of the dialog - but fails to register keypresses.   That is - the machine handles the external file system fine, but something is going wrong with recognizing keypresses, even when no file access is being requested by the program!

I'll get to play with these machines in person...tomorrow.

--
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
Reply | Threaded
Open this post in threaded view
|

Re: KeyListener problem

Fred Damen
Greetings,

From what you state below, I suspect that there is something else that is
looking at the key strokes on that machine.  Is there any other machine(s)
that is exhibiting this issue?  How do you know that there isn't a sniffer
program running on this machine?

In regards to my plugin,
a) The cause/solution may be in those differences.
b) my plugin only does the key handling, the problem may be in the other
stuff you are doing.

enjoy,

Fred

On Wed, March 18, 2020 4:59 pm, Kenneth Sloan wrote:

> yes, well..my code is very similar, and works perfectly on my machine.
>
> the problem is that it does NOT work on at least one other machine.
>
> Latest complication: it seems to matter if the image file is read from an
> external hard drive (on a third machine - not mine).  It displays the
> image and goes through all of the dialog - but fails to register
> keypresses.   That is - the machine handles the external file system fine,
> but something is going wrong with recognizing keypresses, even when no
> file access is being requested by the program!
>
> I'll get to play with these machines in person...tomorrow.
>
> --
> 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
Reply | Threaded
Open this post in threaded view
|

Re: KeyListener problem

Michael Schmid
In reply to this post by Michael Schmid
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
Reply | Threaded
Open this post in threaded view
|

Re: KeyListener problem

Kenneth Sloan-2
In reply to this post by Fred Damen
update:  The plugin has failed on 2 macs, both in the hands of my client.  It works perfectly on my mac, and now we have found that it works perfectly on a WinDoze laptop that I loaned to my client.

Michael Schmid graciously offered to examine the code and test - and could not make it fail.

Both failing laptops were originally set up in the Swiss locale, if that matters - and then changed to USA.  The plugin senses the Locale and adjusts the format of output files, but otherwise  should behave the same way everywhere.

I have no idea what other processes may be running on these macs.

I'm beginning to suspect there is something about how the plugin is being used by this client - right now I'm focusing on "what happens if you minimize a window currently listening for keypresses, and then run the plugin again?"    Or: what happens if there are two independent instantiations of  ImageJ running, both trying to listen to the keyboard?  I'll be testing that on my mac, today.

But...the client is getting his work done, and he is the only one who has ever made it fail, so it's dropping on my priority list.  It is *very* strange, though.

So...we have a plugin that fails on 2 Swiss Mac laptops in the hands of one user - and nowhere else.
And, the user and his wife are in self-quarantine for at least the next week.

The good news is that I cleaned up the code considerably while trying to find a bug in the code.  I could perhaps do a bit more on that front, but I would rather that my client make actual progress on his work rather than pester him with new versions to test.  Finishing the paper takes precedence over solving ImageJ puzzles.

Perhaps in a few weeks I will be able to get my hands on one of his laptops, or (perhaps better) be able to watch over his shoulder as he causes it to fail.  But, for now, we're done...

Thanks to all for your suggestions, and especially to Michael Schmid for testing the plugin in his environment.

--
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