Java 如何更新JSlider';s的最大值,而不发送更改事件

Java 如何更新JSlider';s的最大值,而不发送更改事件,java,swing,jslider,Java,Swing,Jslider,我有一些代码可以更新一个JSlider;在另一个时间点,JSlider的最大值需要更新。问题是,当我在滑块上调用setMaximum()时,它也会调度changevent。为了避免我这样做: slider.removeChangeListener(this); slider.setMaximum(newMax); slider.addChangeListener(this); 有没有一种更干净/更优雅的方法可以做到这一点?您可以检查是谁触发了侦听器中的更改。它仍然很脏,但您不必删除更改侦听器。

我有一些代码可以更新一个
JSlider
;在另一个时间点,
JSlider
的最大值需要更新。问题是,当我在滑块上调用
setMaximum()
时,它也会调度
changevent
。为了避免我这样做:

slider.removeChangeListener(this);
slider.setMaximum(newMax);
slider.addChangeListener(this);

有没有一种更干净/更优雅的方法可以做到这一点?

您可以检查是谁触发了侦听器中的更改。它仍然很脏,但您不必删除更改侦听器。

从本质上看,它看起来像是同一个问题,在这种情况下,我担心答案是“不”

一种干净的方式可能是(取决于您实际需要的内容)要实现一个自定义BoundedRangeModel,该模型触发一个可携带实际更改属性的自定义ChangeEvent:

/**
 * 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;
    }

}

请注意,您必须向模型注册侦听器,而不是向滑块注册侦听器(原因是滑块创建了一个普通类型的新changeEvent)

如果您只需要滑块在值更改时触发事件,您可以通过以下方式简化kleopatra的回答:

// 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();
        }
    });
然后,您所需要做的就是在模型上注册一个“标准”ChangeListener,它只会在值更改时被调用,而不会在最大值或最小值更改时被调用

slider.getModel().addChangeListener(new ChangeListener() {
    public void stateChanged(ChangeEvent e) { 
        // do something here when value changes 
    });

}))

您不能也不应该这样做:在一般情况下,侦听器可能依赖于收到滑块属性所有更改的通知。假设在您的受控上下文中没有,问题仍然是您为什么想要它?闻起来有点像次优设置。@kleopatra是的,你是对的,可能不应该,但这是一个小项目,应该保持简单。它仍然需要在编辑器中编译,因此无论如何都将是一个嵌套类。它有点脏,但能胜任工作。不像我想的那么直截了当,但基本上就是我想要的。你当然可以玩杂耍秋千:)
slider.getModel().addChangeListener(new ChangeListener() {
    public void stateChanged(ChangeEvent e) { 
        // do something here when value changes 
    });