2

So I created a Java application that uses a JSpinner and a ChangeEventListener to run some code when certain values are reached. When those certain values are reached, a JOptionPane appears. But then the JSpinner keeps spinning. So if the JSpinner allowed values 1-50 and I had increased the JSpinner from 20 to 21, it goes all the way to 50 while the JOptionPane is open.

The strange thing is, this was a known bug in Java 1.4.2, but was supposedly fixed in 5.0 (Bug ID: 4840869). I'm running Java 6u37. In fact, the source code provided in the bug issue (shown below) has the exact same effect for me that it did for the original poster of the bug. It most certainly has not been fixed for me.

The only thing that I can think of about why this might be is that I am running Mac OS 10.7.5 and maybe the bug fix didn't make it in to my version somehow. Is there anything I can do to prevent this behavior from happening?

Source code demonstrating this (originally from the bug report):

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class SpinnerFrame extends JFrame implements ChangeListener {

    private JSpinner spinner;

    private boolean changing;

    private SpinnerFrame() {
        super();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().add(getSpinner());
        setSize(80,60);
        setLocation(200, 300);
        setVisible(true);
        changing = false;
    }

    private JSpinner getSpinner() {
        if (spinner == null) {
            spinner = new JSpinner();
            spinner.setModel(new SpinnerNumberModel(10, 1, 50, 1));
            spinner.addChangeListener(this);
        }
        return spinner;
    }

    public void stateChanged(ChangeEvent e) {
        JSpinner spinner = (JSpinner) e.getSource();
        int value = ((Integer) spinner.getValue()).intValue();
        System.out.println("Changed to " + value);
        if (changing) {
            return;
        }
        changing = true;
        if (value > 20) {
            JOptionPane.showMessageDialog(this, "20 exceeded");
            //While this is up, the JSpinner continues to 50
        }
        changing = false;
    }

    public static void main(String[] args) {
        new SpinnerFrame();
    }
}
Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Thunderforge
  • 19,637
  • 18
  • 83
  • 130

2 Answers2

2

I can reproduce a similar effect using either JDK 5 and 6 on an earlier version of Mac OS X. The effect occurs when using the mouse, but not the keyboard.

  1. While the mouse remains pressed on the spinner's up-arrow, the dialog appears at 21.

  2. When the mouse is later released and the first dialog is dismissed, a second dialog appears.

  3. The longer the mouse is held, the higher is the reported value, up to the maximum.

For reference in checking your version, the relevant code mentioned in the bug report is four calls to autoRepeatTimer.stop() in the private static class ArrowButtonHandler found in BasicSpinnerUI. The effect varies by JDK version and may be an artifact of how often the arrow can repeat within the chosen initial delay.

autoRepeatTimer.setInitialDelay(300);
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I'm not quite understanding from your answer what I would do to fix this problem. Is there somewhere I'm supposed to call autoRepeatTimer.setInitialDelay(300)? – Thunderforge Jan 07 '13 at 03:53
  • I'm reporting my findings on JDK versions 5 & 6. Do you see a regression? I don't see a better fix. Why use a modal dialog to report passing the threshold? I'd report it elsewhere via a `PropertyChangeListener`, for [example](http://stackoverflow.com/a/11832979/230513). – trashgod Jan 07 '13 at 04:48
2

I think if you show the message dialog in an EventQueue#invokeLater() it should not have this problem. If you want to cancel the spin to 21 after showing, just reset the value back to 20 after.

Walter Laan
  • 2,956
  • 17
  • 15
  • This ultimately fixed my problem. I actually already have a Factory class for dialog options to simplify the code parameters, so it's really easy for me to implement this. Thank you very much! – Thunderforge Jan 08 '13 at 04:28
  • I've since discovered that this works for just clicking on the up arrow, but if you hold the up arrow down, the repeating dialogs still happen. Any ideas? – Thunderforge Apr 16 '13 at 19:11
  • Do a check if the dialog is currently showing and don't reshow if it is. – Walter Laan Apr 17 '13 at 09:56
  • I wound up doing that and it worked. Unfortunately, I also had to check how long it had been since the last one displayed because as soon as I reset the variable preventing it from appearing, one more would appear. – Thunderforge Apr 17 '13 at 17:59