# JSpinner ChangeEvent erzwingen



## BlubBlub (5. Okt 2011)

Hi ich verwende einen JSpinner.
Dieser JSpinner hat einen ChangeListener.
Der ChangeListener wird jedes mal ausgelöst, sobald
sich der Wert im JSpinner ändert.
Zusätzlich habe ich einen JButton.
Der JButton hat einen ActionListener.
Dieser wird bei jedem betätigen des Buttons ausgelöst.
Im ActionListener steht ein Befehl der den Wert des
JSpinners auf 11 setzt. 
War der Wert im JSpinner vorher nicht 11 so wird nach dem 
Betätigen des JButtons der ChangeListener des JSpinner
aufgerufen. War der Wert im JSpinner aber vorher bereits 11 
so wird der ChangeListener nicht aufgerufen.

Frage: Wie schaffe ich es, dass der ChangeListener dennoch 
aufgerufen wird auch wenn der Wert im JSpinner vorher 11 war?



```
public class MyFrame extends JFrame
{	
	private JSpinner spinner;
	
	public MyFrame()
	{
		super();
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setLayout(new FlowLayout());
		
		Container contentPane = this.getContentPane();
		
		SpinnerModel model = new SpinnerNumberModel(0, 0, 100, 1); 
		spinner = new JSpinner(model);
		spinner.addChangeListener(new ChangeListener(){

			@Override
			public void stateChanged(ChangeEvent arg0) {
				System.out.println("Change Listener");
			}});
		
		JButton button = new JButton("Button");
		button.addActionListener(new ActionListener(){

			@Override
			public void actionPerformed(ActionEvent arg0) {
				spinner.setValue(new Integer(11));
			}});
		
		contentPane.add(spinner);
		contentPane.add(button);
		
		this.setSize(500, 400);
		this.setVisible(true);
	}
}
```


----------



## eRaaaa (5. Okt 2011)

Vermutlich indem du dir ein eigenes SpinnerModel schreibst, bzw. das jetzige überschreibst. Denn wenn man sich das SpinnerNumberModel anschaut, sieht man dass das Event in der setValue Methode geworfen wird (allerdings eben nur wenn das value != das alte ist):

```
public void setValue(Object value) {
	if ((value == null) || !(value instanceof Number)) {
	    throw new IllegalArgumentException("illegal value");
	}
	if (!value.equals(this.value)) {  //diese abfrage raus nehmen!
	    this.value = (Number)value;
	    fireStateChanged();
	}
    }
```
Die Frage ist allerdings. Wieso will man das? Was bringt dir das? :bahnhof:


----------



## Marco13 (5. Okt 2011)

Die Frage hätte ich so ähnlich auch gestellt. Wenn man will, dass ein ChangeEvent geworfen wird, obowhl nichts gechanged wurde, kann man ja gleich

```
new Thread(new Runnable() { public void run() { System.out.println("Aaaaa..."); } }).start();
```
machen 

Oder anders: Was soll bei dem ChangeEvent passieren, was nicht auch bei dem ActionEvent passieren könnte?


----------



## bERt0r (5. Okt 2011)

Oder ganz einfach: du lagerst den code vom ChangedListener in einer Methode aus und rufst die dann vom ActionListener auf.

```
void changedSpinner()
{
//Code von deinem alten ChangeListener
}
spinner.addChangeListener(new ChangeListener()
{public void valueChanged(ChangeEvent e)
{changedSpinner();}
});
button.addActionListener(new ActionListener()
{public void actionPerformed(ActionEvent e)
{
spinner.setValue(11);
changedSpinner();
}
});
```


----------



## eRaaaa (5. Okt 2011)

bERt0r hat gesagt.:


> Oder ganz einfach:



Theoretisch schon, aber ganz so leicht wie du es hier darstellst ist es dann doch nicht, denn so würdest du (bis auf den Fall wenn Value 11 ist) jedes mal zwei mal changedSpinner() aufrufen wenn der Button gedrückt wird  (wenn denn die richtige Methode implementiert wird vom ChangeListener :bae Ob das nun Auswirkungen haben kann oder nicht - wer weiß das hier schon so genau :shock:

/e...das ist mir schon klar hdi....


----------



## hdi (5. Okt 2011)

> Theoretisch schon, aber ganz so leicht wie du es hier darstellst ist es dann doch nicht, denn so würdest du (bis auf den Fall wenn Value 11 ist) jedes mal zwei mal changedSpinner() aufrufen wenn der Button gedrückt wird



Naja das ist jetzt nicht so das Problem:


```
actionPerformed{
   int neuerWert = gui.getSpinnerWert();
   int alterWert = spinner.getValue();
   spinner.setValue(neuerWert);
   if(neuerWert == alterWert){ // also nur dann
        change event feuern
   )
}
```

Das man es so nicht machen sollte hat eher den Hintergrund dass es vom Design her nicht passt. Wenn sich nix geändert hat sollte auch kein ChangeEvent auftreten. Nicht umsonst ist das so implementiert, und nicht umsonst heißt der auch ChangeListener und nicht MaybeChangeListener.

D.h. in der actionPerformed sollte er kein Change-Event feuern, sondern sein Zeug direkt machen. Wenn es da eine Redundanz zwischen dieser Aktion und der Aktion nach einem ChangeEvent kommt dann eben auslagern, genauso wie bert0r es gepostet hat.

@TO: Im Endeffekt also der Code von bert0r kombiniert mit dem obigen ActionListener. Aber nenn die Methode in die du auslagerst besser nicht spinnerChanged, das wäre wieder irreführend. Nenn sie lieber spinnerTouched o.ä.


----------



## BlubBlub (10. Okt 2011)

Okay danke für die Hinweise =)


----------

