Reputation: 51837
I have wee bit of code that updates a JSlider
; and at another point in time, the JSlider
's maximum value needs to updated. The problem is when I call setMaximum()
on the slider, it also dispatches a ChangeEvent
. To avoid that I'm doing this:
slider.removeChangeListener(this);
slider.setMaximum(newMax);
slider.addChangeListener(this);
Is there a cleaner/more elegant way of doing this?
Upvotes: 1
Views: 1973
Reputation: 63
if you just need your slider to fire events when value is changing you can simplify kleopatra's answer in the following way:
// make sure slider only fires changEvents when value changes
slider.setModel(new DefaultBoundedRangeModel() {
final ChangeEvent theOne=new ChangeEvent(this);
@Override
public void setRangeProperties(int newValue, int newExtent, int newMin,int newMax, boolean adjusting)
changeEvent= (getValue() != newValue ? theOne:null);
super.setRangeProperties(newValue, newExtent, newMin, newMax, adjusting);
}
@Override
protected void fireStateChanged()
{
if(changeEvent==null) return;
super.fireStateChanged();
}
});
Then all you need to do is register a "Standard" ChangeListener on the model and it will only get called when the value is changing not when maximum or minimum changes.
slider.getModel().addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
// do something here when value changes
});
});
Upvotes: 0
Reputation: 51525
A clean way might be (depending a bit on what you actually need) to implement a custom BoundedRangeModel which fires a custom ChangeEvent that can carry the actually changed properties:
/**
* Extended model that passes the list of actually changed properties
* in an extended changeEvent.
*/
public static class MyBoundedRangeModel extends DefaultBoundedRangeModel {
public MyBoundedRangeModel() {
}
public MyBoundedRangeModel(int value, int extent, int min, int max) {
super(value, extent, min, max);
}
@Override
public void setRangeProperties(int newValue, int newExtent, int newMin,
int newMax, boolean adjusting) {
int oldMax = getMaximum();
int oldMin = getMinimum();
int oldValue = getValue();
int oldExtent = getExtent();
boolean oldAdjusting = getValueIsAdjusting();
// todo: enforce constraints of new values for all
List<String> changedProperties = new ArrayList<>();
if (oldMax != newMax) {
changedProperties.add("maximum");
}
if (oldValue != newValue) {
changedProperties.add("value");
}
// todo: check and add other properties
changeEvent = changedProperties.size() > 0 ?
new MyChangeEvent(this, changedProperties) : null;
super.setRangeProperties(newValue, newExtent, newMin, newMax, adjusting);
}
}
/**
* Extended ChangeEvent that provides a list of actually
* changed properties.
*/
public static class MyChangeEvent extends ChangeEvent {
private List<String> changedProperties;
/**
* @param source
*/
public MyChangeEvent(Object source, List<String> changedProperties) {
super(source);
this.changedProperties = changedProperties;
}
public List<String> getChangedProperties() {
return changedProperties;
}
}
Its usage something like:
final JSlider slider = new JSlider();
slider.setModel(new MyBoundedRangeModel(0, 0, -100, 100));
ChangeListener l = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
if (e instanceof MyChangeEvent) {
MyChangeEvent me = (MyChangeEvent) e;
if (me.getChangedProperties().contains("value")) {
System.out.println("new value: " +
((BoundedRangeModel) e.getSource()).getValue());
}
if (me.getChangedProperties().contains("maximum")) {
System.out.println("new max: " +
((BoundedRangeModel) e.getSource()).getMaximum());
}
} else {
// do something else or nothing
}
}
};
slider.getModel().addChangeListener(l);
Note that you have to register the listener with the model, not with the slider (reason being that the slider creates a new changeEvent of the plain type)
Upvotes: 3
Reputation: 818
It looks like the same problem, in essence, as this question. In which case, I fear the answer is "no"
Upvotes: 0
Reputation: 1533
You could check who triggered the change in the listener. It's still pretty dirty but you won't have to remove the change listener.
Upvotes: 0