当另一个组件触发事件时,请勿触发事件

时间:2012-10-01 11:19:14

标签: java swing jslider jspinner changelistener

我有一个JSlider和JSpinner,它们彼此“链接”。所以JSpinner显示了JSlider的值。现在,当我移动JSlider时,我需要更改JSpinner的值(反之亦然)。

我现在的问题是更改(例如移动滑块)它将更新JSpinner的值,这将更新滑块的位置。幸运的是,这不会再次触发JSpinner的更新。但是我想防止这个事件被触发两次。

所以现在我的问题是,有可能以某种方式说事件中的变化不会再次触发事件吗?

费边

1 个答案:

答案 0 :(得分:0)

您可以通过从相应组件中添加和删除侦听器的每个调用来做到这一点。因此,您需要保留共享侦听器的引用,例如以下示例代码:

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);
        });
    }
}

当然,您也可以使用两个不同的实例(每个ChangeListener的单独子类)来实现它,然后在创建之后,使用setter分配例如应该链接的另一个组件。

或者您可以在ChangeListener的实例中使用布尔标志(让一个人知道何时被另一个调用),而不必删除,然后在每次侦听组件时再次添加回去