Re: Suppresing events to avoid fibrillation
In article <h5pnj5t7eqejbsq0ho9n03025u9m22ga2r@4ax.com>,
Roedy Green <see_website@mindprod.com.invalid> wrote:
I run into this problem frequently. I call it fibrillation.
Lets say I do a setText on some component. This triggers an event on
it. That event handler then might do setText's on other components.
If you are really unlucky, you get a circularity.
Interestingly, one model of cardiac fibrillation involves an analogous
kind of circularity:
<http://en.wikipedia.org/wiki/Cardiac_arrhythmia#Re-entry>
What would like to do is a sneaky programmatic setText that does NOT
trigger any events, other than perhaps a repaint.
What I have been doing is somewhat klutzy. I have some ad hoc
booleans. When I don't want an event to be acted on, I set the
boolean, then detect it in the event handler, and turn it off.
You need one boolean for each possible event that might be triggered.
If it is not triggered, the event improperly stays suppressed.
Is there a clean way to do this?
It's no panacea, but assiduously separating the model and views seems to
mitigate this somewhat. Each control updates the model only, never
another view. The model then notifies the views that the model's state
has changed. The views then query the model for the new state and repaint
themselves. I often have the model extend Observable to notify the views,
each of which implements Observer. Observers can compare the model value
to their own state and ignore null changes.
Here's my favorite picture:
<http://java.sun.com/blueprints/patterns/images/mvc-structure-generic.gif>
Of course, sometimes I just have each listener update the other component:
<fragment>
public class SpinSlider extends JPanel {
public SpinSlider() {
this.setLayout(new FlowLayout());
final JSpinner spinner = new JSpinner();
final JSlider slider = new JSlider();
slider.addChangeListener(new ChangeListener() {
//@Override
public void stateChanged(ChangeEvent e) {
JSlider s = (JSlider) e.getSource();
spinner.setValue(s.getValue());
}
});
this.add(slider);
spinner.setModel(new SpinnerNumberModel(50, 0, 100, 1));
spinner.addChangeListener(new ChangeListener() {
//@Override
public void stateChanged(ChangeEvent e) {
JSpinner s = (JSpinner) e.getSource();
slider.setValue((Integer) s.getValue());
}
});
this.add(spinner);
}
}
</fragment>
--
John B. Matthews
trashgod at gmail dot com
<http://sites.google.com/site/drjohnbmatthews>