1

I have a JSlider and JSpinner which are “linked” to each to each other. So the JSpinner shows the value of the JSlider. Now when I move the JSlider I need to change the value of the JSpinner (and vice versa).

My problem now is that the changing (e.g. you move the slider) it will update the value of the JSpinner which will update the slider's position. Luckily this won't trigger an update of the JSpinner again. But I want to prevent that this event will be triggered twice.

So my question is now, is it possible to say somehow that the change within the event won't trigger the event again?

Fabian

mKorbel
  • 109,525
  • 20
  • 134
  • 319
xZise
  • 2,321
  • 5
  • 22
  • 31
  • 2
    for better help sooner post and [SSCCE](http://sscce.org/) , otherwise there are some code about BoundedRangeModel and (Property)ChangeListener – mKorbel Oct 01 '12 at 11:24
  • 2
    [`SpinSlider`](http://stackoverflow.com/a/6067986/230513) may be a useful example. – trashgod Oct 01 '12 at 11:26
  • The SpinSlider shows exactly what my problem is: When you debug the code you see, that both events are triggered when you change only one thing. For example I added a System.out.println(…) to both events and both println() get triggered when I change the spinner's value. – xZise Oct 01 '12 at 15:56

1 Answers1

0

Well you can do this by adding and removing the listener for each of its invocations from the corresponding component. So you need to keep a reference of the shared listener like the following sample code:

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class SpinnerAndSlider extends JPanel {

    public static void main(final String args[]) {

        SwingUtilities.invokeLater(() -> {

            final JSlider slider = new JSlider();
            final JSpinner spinner = new JSpinner(new SpinnerNumberModel(slider.getValue(), slider.getMinimum(), slider.getMaximum(), 1));

            final ChangeListener listener = new ChangeListener() {
                @Override
                public void stateChanged(final ChangeEvent cevt) {
                    if (cevt.getSource() == spinner) {
                        slider.removeChangeListener(this);
                        slider.setValue((Integer) spinner.getValue());
                        slider.addChangeListener(this);
                    }
                    else if (cevt.getSource() == slider) {
                        spinner.removeChangeListener(this);
                        spinner.setValue(slider.getValue());
                        spinner.addChangeListener(this);
                    }
                }
            };

            slider.addChangeListener(listener);
            spinner.addChangeListener(listener);

            final JPanel contents = new JPanel(); //FlowLayout.
            contents.add(slider);
            contents.add(spinner);

            final JFrame f = new JFrame("Spinner with Slider");
            f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            f.getContentPane().add(contents);
            f.pack();
            f.setLocationRelativeTo(null);
            f.setVisible(true);
        });
    }
}

Of course you could also implement it with two different instances (each one of a separate subclass of ChangeListener) and then, after creation, assign with a setter for example the other component which is supposedly linked.

Or you could use boolean flags in the instances of the ChangeListener (for the one to know when it is called by the other) instead of having to remove and then adding back again each time the listener to the components.

gthanop
  • 3,035
  • 2
  • 10
  • 27