Pergunta

I made a JSpinner component with a SpinnerNumberModel as model like this:

JSpinner spinbox = new JSpinner(new SpinnerNumberModel(2, 1, 7, 1));

I added a listener to detect changes.

spinbox.addChangeListener(new ChangeListener() {
    @Override
    public void stateChanged(ChangeEvent arg0) {
        synchronized (this) {
            System.out.println("New value: " +
              ((Integer)_spiNumOfAIs.getValue()).intValue());
        }
    }
});

All I see, however, is this:

New value: 0

New value: 0

Am I reading out the value of the spinbox incorrectly?

In case you're wondering about the synchronized block: I'm new to Swing and I don't know whether action listeners are executed on the same thread where I created my JDialog or not, so I put in thread safety measures for all action listeners to be safe. _spiNumOfAIs is a member variable.

Edit: even from this small code snippet it's so obvious that I didn't even see it... while refactoring I forgot that I'm using both a JSpinner spinbox and a JSpinner _spiNumOfAis, with the former being the spinner that is visible in the GUI.

Foi útil?

Solução

All Swing operations should be performed on the EDT, and as a result interacting with your UI always happens on the EDT. In short, your ChangeListener will be called on the EDT so no need for the synchronize. You can easily verify this by using EventQueue.isDispatchThread in your listener, which will return true. This is explained in the Swing concurrency lesson, from which I quote:

The event dispatch thread, where all event-handling code is executed. Most code that interacts with the Swing framework must also execute on this thread.

To further answer your problem with the incorrect value, you should post more code allowing us to reproduce your problem. For example this is a very basic working example of a spinner

import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.EventQueue;

public class JSpinnerDemo {

  public static JFrame createFrame(){
    JFrame frame = new JFrame(  );
    frame.add( createSpinner() );
    frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    frame.pack();

    return frame;
  }

  public static JSpinner createSpinner(){
    JSpinner spinner = new JSpinner( new SpinnerNumberModel( 2,1,7,1 ) );
    spinner.addChangeListener( new ChangeListener() {
      @Override
      public void stateChanged( ChangeEvent e ) {
        JSpinner spinner = ( JSpinner ) e.getSource();
        SpinnerModel spinnerModel = spinner.getModel();
        System.out.println(spinnerModel.getValue());
      }
    } );
    return spinner;
  }
  public static void main( String[] args ) {
    EventQueue.invokeLater( new Runnable() {
      @Override
      public void run() {
        createFrame().setVisible( true );
      }
    } );
  }
}

Feel free to modify this to illustrate your problem. I can also suggest to take a look at the JSpinner class javadoc since the editor and the model value might get out of sync, as explained in the javadoc. Another good starting point is the Swing tutorial about spinners

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top