JavaFX将UI绑定到嵌套类的属性

时间:2017-07-12 15:44:44

标签: java javafx observable

我有一个名为Passage的类,它包含一个名为Action的非可观察类。 Action包含SimpleStringProperty

class Passage {

    Action action = null;

    Action getAction() { return action; }

    void setAction(Action action) { this.action = action; }

    boolean hasAction() { return action != null; }
}

class Action {

    StringProperty myStringProperty = new SimpleStringProperty();

    StringProperty getStringProperty() { return myStringProperty; }

    // and other methods, many of which modify myStringProperty
}

我想将该字符串属性绑定到UI标签。看起来这应该是一件简单的事情:

label.textProperty.bind(passage.getAction().getStringProperty());

但是,Action有时可能为空。我尝试过以下方法:

label.textProperty.bind(passage.hasAction() ? passage.getAction().getStringProperty() : new SimpleStringProperty("") );

然后,如果Action开始为null(因此标签开始为空)然后将Action分配给非null(即调用setAction()),则标签不会更新以反映更改。 / p>

我是否需要观察动作?请参阅:Binding to javafx properties of a object that can be null

上述解决方案使用了我不熟悉的monadic操作。所以我读了这篇有用的博文:http://tomasmikula.github.io/blog/2014/03/26/monadic-operations-on-observablevalue.html

我尝试使用EasyBind进行此绑定。

我创建了一个包含ObservableAction的新类Action,使其成为可观察的值(虽然我不确定我是否正确执行了此步骤):

import javafx.beans.binding.ObjectBinding;

public class ObservableAction extends ObjectBinding <Action>
{
    private final Action value;

    public ObservableAction(Action action) {
        this.value = action;
    }

    @Override
    public Action computeValue()
    {
        return value;
    }
}

然后我在ViewController中有以下代码(再次,不确定我是否正确地完成了这项操作):

MonadicObservableValue<Action> monadicAction = EasyBind.monadic(new ObservableAction(passage.getAction()));

actionLabel.textProperty().bind(monadicAction.flatMap(action -> action.getTextProperty()).orElse(""));

结果与我以前经历的结果相同:当Action不为空时,它可以正常工作。但是,如果Action开始为null,然后变为非null,则标签不会更新。

1 个答案:

答案 0 :(得分:1)

我建议在Passage中拥有一个属性,该属性将与action的属性绑定。 设置新操作后,绑定它的属性并仅使用Passage的属性。

class Passage {
    private Action action;

    private StringProperty actionMyStringProperty = new SimpleStringProperty();

    void setAction(Action action) {
        this.action = action;

        // Unbind the previous binding if any (it is safe when nothing to unbind).
        actionMyStringProperty.unbind();

        if (action != null){
            actionMyStringProperty.bind(action.getStringProperty());
        }
    }

    public StringProperty actionMyStringProperty() {
        return actionMyStringProperty;
    }
}

class Action {
    private StringProperty myStringProperty = new SimpleStringProperty();

    StringProperty getStringProperty() {
        return myStringProperty;
    }
}

在客户端:

label.textProperty.bind(passage.actionMyStringProperty());