【问题标题】:How to make a SimpleProperty inform listeners on the first set?如何让 SimpleProperty 在第一组通知听众?
【发布时间】:2019-03-24 11:02:08
【问题描述】:

当我写这个时:

import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ChangeListener;

SimpleBooleanProperty foo = new SimpleBooleanProperty();
foo.addListener(
    new ChangeListener<Boolean>() {
        @Override
        public void changed(
             ObservableValue<? extends Boolean> observable,
             Boolean oldValue, Boolean newValue
        ) {
            System.out.println(oldValue + " " + newValue);                    
        }
    }
);
foo.set(false);
foo.set(true);

输出是

false true

但是,如果我将最后两行更改为

foo.set(true);
foo.set(false);

输出是

false true
true false

我觉得这很矛盾。如何确保始终在第一个 set 上通知侦听器?

... 或者,侦听器应该显式调用foo.get() 以获取初始值,然后仅获知更改是常识吗?在那种情况下,我仍然不知道如何区分默认的false 和在监听器注册之前设置的false

【问题讨论】:

  • 迈克尔的回答是正确的。它被称为 更改监听器,因为它仅在值实际更改时触发。
  • 你为什么要那个?听起来像次优设置...
  • @kleopatra 为什么你认为它不是最理想的?
  • probability ;) 您在注册时就知道该值,那么您为什么希望该属性变为非法并使用 old== new 开除某些东西?想不出一个重要的背景
  • @kleopatra 我认为我真正想要的是ActionListener,每次设置值时都会收到通知。我很困惑,因为同时我确实需要ChangeListener 来获得更改通知。我想我会写一个答案,也许可以澄清我所追求的

标签: java javafx properties listener


【解决方案1】:

完全一致。

问题在于SimpleBooleanProperty已经初始化为 false。当您首先调用 foo.set(false) 时,值实际上并没有改变,因此不会调用侦听器。

当您首先调用foo.set(true) 时,值会更改两次(false -> true -> false),这会调用两次侦听器。

如果您希望初始值为真,请使用the constructor which takes a boolean


如果你想在附加监听器时触发一个事件,你可以很容易地扩展SimpleBooleanProperty,虽然我不清楚你会为旧值使用什么(我猜是null?):

class FireWhenAttachBooleanProperty extends SimpleBooleanProperty
{
    @Override
    public void addListener(ChangeListener<? super Boolean> listener)
    {
        super.addListener(listener);
        listener.changed(this, null, getValue());
    }
}

【讨论】:

  • 唯一有效的旧值是...旧值;)
  • @kleopatra 你可以几乎通过让FireWhenAttachBooleanProperty 倾听自己来解决这个问题......我觉得自己像个疯狂的科学家
  • hmm .. 将删除我的第一条评论,因为考虑到它,我并不完全确定 ;) 不确定 oldvalue == newValue 是否是一个有效的通知 - 可能不是,因为该属性保证会触发仅当两者不同时
【解决方案2】:

也许问题并不清楚(如果是的话,我想我不必问这个问题;)。我的错误是我实际上想对两种不同的事情做出反应:每次设置值时都应通知一种侦听器,而仅在更改值时才通知另一种侦听器。所以我实际上需要这样的东西:

import javafx.event.EventHandler;
import java.util.ArrayList;
import javafx.event.ActionEvent;
import javafx.event.Event;

class Foo {
    private SimpleBooleanProperty foo = new SimpleBooleanProperty();
    private ArrayList<EventHandler> listener = new ArrayList<>();
    public void set(Boolean value) {
        foo.set(value);
        ActionEvent e = new ActionEvent();
        for(EventHandler l : listener) l.handle(e);
    }
    public void addChangeListener(ChangeListener<Boolean> x) { 
        foo.addListener(x); 
    }
    public void addEventHandler(EventHandler a){
        listener.add(a);
    }
}

这样我就可以这样写了:

Foo foo = new Foo();
foo.addChangeListener(new ChangeListener<Boolean>() {
    @Override
    public void changed(ObservableValue<? extends Boolean> observable,
                        Boolean oldValue, 
                        Boolean newValue) {
        System.out.println("value changed");                
    }            
});
foo.addEventHandler(new EventHandler() {
    @Override
    public void handle(Event event) {
        System.out.println("value was set");
    }            
});        
foo.set(false);

即使值没有改变,也会通知事件处理程序。

【讨论】:

    猜你喜欢
    • 2011-09-24
    • 1970-01-01
    • 2021-08-31
    • 2017-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-05
    相关资源
    最近更新 更多