Как заставить SimpleProperty информировать слушателей о первом наборе? - PullRequest
0 голосов
/ 19 октября 2018

Когда я пишу это:

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, которое было установлено до регистрации слушателя.

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

Может быть, это не было ясно из вопроса (если это было так, я думаю, мне не нужно было задавать вопрос;).Моя ошибка заключалась в том, что я действительно хотел реагировать на две разные вещи: один вид слушателя должен уведомляться каждый раз, когда устанавливается значение, и другой тип слушателя только при изменении значения.Так что мне на самом деле нужно что-то вроде этого:

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

, где даже если значение не меняется, обработчик событий получает уведомление.

0 голосов
/ 19 октября 2018

Это совершенно непротиворечиво.

Проблема в том, что SimpleBooleanProperty уже уже инициализировано как false .Когда вы сначала вызываете foo.set(false), то значение фактически не изменяется, поэтому слушатель не вызывается.

Когда вы сначала вызываете foo.set(true), тогда значение меняется дважды (false -> true -> false)который вызывает слушателя дважды.

Если вы хотите, чтобы начальное значение было истинным, используйте конструктор, который принимает логическое значение .


Если вы хотите запуститьсобытие при подключении слушателя, вы можете довольно легко расширить SimpleBooleanProperty, хотя мне не ясно, что бы вы использовали для старого значения (я думаю, ноль):

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