Я столкнулся с этой проблемой в приложении большего масштаба, где некоторые пользовательские привязки не обновлялись при изменении значения свойства источника.Пользовательские привязки JavaFX не работают
Мне удалось написать простой класс, чтобы воспроизвести эту проблему, и я действительно не понимаю, почему это происходит. Вот быстрый тест, который воспроизводит проблему:
import javafx.beans.binding.BooleanBinding;
import javafx.beans.binding.ObjectBinding;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
public class TestingBindingsFx {
private final ObjectProperty<MyEvent> objectProperty = new SimpleObjectProperty<MyEvent>(this, "objectProperty");
private final BooleanProperty booleanProperty = new SimpleBooleanProperty(this, "booleanProperty");
private ObjectBinding<MyEvent> bindingObj;
private BooleanBinding bindingBool;
public TestingBindingsFx(ObjectProperty<String> selection) {
setupBindings(selection);
}
private void setupBindings(ObjectProperty<String> selection) {
bindingObj = createObjectBinding(selection);
bindingBool = createBooleanBinding(selection);
objectProperty.bind(bindingObj);
booleanProperty.bind(bindingBool);
}
private static ObjectBinding<MyEvent> createObjectBinding(ObjectProperty<String> selection) {
return new ObjectBinding<MyEvent>() {
{
super.bind(selection);
}
@Override
protected MyEvent computeValue() {
System.out.println("createObjectBinding called");
MyEvent ve = selection.get() == null ? MyEvent.EVENT1
: MyEvent.EVENT2;
return ve;
}
};
}
private static BooleanBinding createBooleanBinding(ObjectProperty<String> selection) {
return new BooleanBinding() {
{
super.bind(selection);
}
@Override
protected boolean computeValue() {
System.out.println("createBooleanBinding called");
return selection.get() == null ? true : false;
}
};
}
public static void main(String[] args) {
ObjClass objclass = new ObjClass();
System.out.println("Instantiating TestingBindingsFx...");
TestingBindingsFx fx = new TestingBindingsFx(objclass.selection);
objclass.selection.addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
System.out.println("changed " + oldValue + "->" + newValue);
}
});
System.out.println("Changing selection property values...");
objclass.selection.set("Test 1");
objclass.selection.set("Test 2");
}
enum MyEvent {
EVENT1,
EVENT2;
}
static class ObjClass {
public final ObjectProperty<String> selection = new SimpleObjectProperty<String>(this, "selection");
}
}
Таким образом, после запуска этого я вижу:
Instantiating TestingBindingsFx... createObjectBinding called createBooleanBinding called Changing selection property values... changed null->Test 1 changed Test 1->Test 2
Когда я ожидал увидеть что-то вроде:
Instantiating TestingBindingsFx... createObjectBinding called createBooleanBinding called Changing selection property values... changed null->Test 1 createObjectBinding called createBooleanBinding called changed Test 1->Test 2 createObjectBinding called createBooleanBinding called
ChangeListener
работает как ожидалось (просто поставьте его там для целей проверки), и его вызывают каждый раз, когда я изменяю значение свойства выбора.
Но пользовательские привязки никогда не обновляются после первого раза и смотрят на код, который я не могу понять, почему. Сначала я думал, что это может быть связано со слабыми ссылками, но я даже превратил объекты привязки в переменные уровня класса и все же никаких изменений.
Я чувствую, что здесь может быть что-то важное, но после двух часов просмотра этого кода я просто не понимаю, почему. В моем реальном приложении это еще более странно, потому что одно из пользовательских привязок действительно работает нормально.
Бинго, вот и все! Я знал, что мне не хватает чего-то простого, я был настолько сосредоточен на том, что computeValue не называется, что полностью забыл о ленивом характере привязок. Мне не нужно принудительно пересчитывать, ленивость совершенно прекрасна. Мне просто не хватало, чтобы прочитать целевые свойства обратно на свой тестовый код после изменения значений свойств источника. Спасибо за быстрый ответ. – mfc