For a PropertyChangeSupport to work you need to call its firePropertyChange
method, but more importantly the support object needs to have access to the setXXX method of the property that it is listening to, and in that method it needs to call PropertyChangeSupport's firePropertyChange method. And so I think for your idea to work, you'll need to extend the model's class, give it a PropertyChangeSupport object, give it the add and remove listener methods, and be sure to listen to changes made in the model's setValue method which is key. In my example that method looks like this:
@Override
public void setValue(Object newValue) {
// store old value and set the new one
Object oldValue = getValue();
super.setValue(newValue);
// construct the event object using these saved values
PropertyChangeEvent evt = new PropertyChangeEvent(this, VALUE, oldValue,
newValue);
// notify all of the listeners
pcs.firePropertyChange(evt);
}
Here's my sample model class that uses PropertyChangeSupport:
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;
@SuppressWarnings("serial")
class MySpinnerNumberModel extends SpinnerNumberModel {
public static final String VALUE = "value";
private SwingPropertyChangeSupport pcs = new SwingPropertyChangeSupport(this);
// you will likely need to create multiple constructors to match
// the ones available to the SpinnerNumberModel class
public MySpinnerNumberModel(int value, int min, int max, int step) {
super(value, min, max, step);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
@Override
public void setValue(Object newValue) {
// store old value and set the new one
Object oldValue = getValue();
super.setValue(newValue);
// construct the event object using these saved values
PropertyChangeEvent evt = new PropertyChangeEvent(this, VALUE, oldValue,
newValue);
// notify all of the listeners
pcs.firePropertyChange(evt);
}
}
And finally the test class to test out the above class to see if it is working properly:
import java.beans.*;
import javax.swing.*;
public class TestSpinnerPropChange {
private static void createAndShowUI() {
final MySpinnerNumberModel myModel = new MySpinnerNumberModel(1, 0, 10, 1);
final JSpinner spinner = new JSpinner(myModel);
final JTextField oldValueField = new JTextField(10);
final JTextField newValueField = new JTextField(10);
JPanel panel = new JPanel();
panel.add(spinner);
panel.add(new JLabel("old value:"));
panel.add(oldValueField);
panel.add(new JLabel("new value:"));
panel.add(newValueField);
myModel.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
// checking the property name is overkill here, but is a good habit
// to get into, especially if listening to more than one property.
if (evt.getPropertyName().equals(MySpinnerNumberModel.VALUE)) {
oldValueField.setText(evt.getOldValue().toString());
newValueField.setText(evt.getNewValue().toString());
}
}
});
JFrame frame = new JFrame("TestSpinnerPropChange");
frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
createAndShowUI();
}
});
}
}