tags:

views:

154

answers:

4

Dear All, I wrote the following piece of code, which is supposed to return a panel with one checkbox and one button. The idea is that the button should be enabled only if the checkbox is checked. It works, meaning that if the checkbox is not checked, and I try to push the button, nothing happens. However, the visual appearance of the button is wrong, it appears as disabled when it should appear as enabled, and vice-versa. Any idea what's wrong with my code ? Thanks a lot in advance

public Panel createCalibrationPanel(final ImagePlus imp) {
    final Panel panel = new Panel();
    panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
    panel.add(Box.createHorizontalStrut(20));
    final Checkbox checkbox = new Checkbox(
            "Use image spatial calibration for q scale", true);
    final Button button = new Button("Set scale");
    useCalibration = checkbox.getState();
    button.setEnabled(checkbox.getState());
    panel.add(checkbox);
    panel.add(button);
    checkbox.addItemListener(new ItemListener() {
        public void itemStateChanged(final ItemEvent e) {
            boolean state = checkbox.getState();
            setUseCalibration(state);
            button.setEnabled(state);
        }
    });
    button.addActionListener(new ActionListener() {
        public void actionPerformed(final ActionEvent e) {
            imp.unlock();
            IJ.run(imp, "Set Scale...", "");
            imp.lock();
        }
    });
    return panel;
}
A: 

I was pretty sure you're doing everything correctly, and my test bore this out. I removed the image reference and the action code, and the button behaves as intended.

I'm running JDK 6 from Sun on Ubuntu Linux. But that shouldn't make any difference.

I wonder if imp.lock() is doing something heinous. If this is the kind of lock associated with synchronization and concurrent processing, it looks intuitively wrong, because you're keeping the poor imp locked up for most of the program's lifetime. In any case, you could have a look at what happens when you comment out the action code.

Carl Smotricz
lock() tells ImageJ that imp is not available for any *OTHER* plugin to process it. So the image is not locked with regard to the currently running plugin (not sure I'm totally clear).
Sebastien
+1  A: 

The logic controlling the button is correct. I modified your sample code and it works as you described. (This is the version I used: http://pastebin.com/f6cd6cfac, tested on Sun Java 6).

But, there are some other methods that you call, but which you haven't shown us: setUseCalibration, imp.unlock, and IJ.run. Are you sure they are returning correctly? You should remove the external calls from code, and add them back in one at time until you find which one(s) is causing the problem.

sjf
I wonder if this has to do with my using java under macos? I'll give it a try tonight on a windows machine. Meanwhile, removing all irrelevant code doesn't change anything...
Sebastien
That's what I wanted to hear. If the "bare metal" code works incorrectly then it's Steve Jobs' fault :) (or at least evidence to that effect is mounting).
Carl Smotricz
I confirm... tried the full program on a windows box, and it works just fine... Who said windows was faulty... In the ImageJ framework, there actually exists a method called "isMacOSX()", which tells a lot...
Sebastien
A: 

I can't reproduce the problem either using Sun Java 6 on 64 bit OpenSuse 11.0. However, this doesn't mean that the code is correct. It just happens to work for me on my machine, OS and JRE today.

From your description it sounded like button.setEnabled(state) wasn't updating the appearance of the button, so I wondered if adding a button.repaint() directly after the call would make it work? This is more of an experiment than a solution, as even if it works it doesn't explain why your original code runs for me and not for you.

Either way I suspect one of:

  • Something in the way that the code is called.
  • Something in the library code.
  • A bug in the JRE (if it's a Sun JRE you can search the bugs database).
  • A threading problem (make sure that the AWT code runs on the EventDispatchThread and synchronize on mutable data members that are shared between threads).
richj
Maybe the cause for my bug is item #4, since I haven't done anything particular regarding threads. The thing is this code is part of an ImageJ plugin, and ImageJ should handle this. For what it's worth, the problem does not occur if I replace Buttons with JButtons.
Sebastien
Oh, and by the way! I tried repaint()... didn't work!
Sebastien
A: 

OK, I am getting more and more confused:

  • tried it on Windows, no problem.
  • under Mac OS X, the state of the checkbox and the button are synchronised, but not the visual appearance of the button, but the bug does not occur if you change the state of the checkbox with the keyboard instead of the mouse.

So it seems there is a bug in apple's implementation of Java/AWT, and I need to live with it. Any idea for a workaround? I think I need to take advantage of the fact that a keyboard driven event leads to the expected behaviour. How can I emulate a keyboard event when a mouse event is caught?

Sebastien