JavaFX复杂字符串绑定

JavaFX复杂字符串绑定,java,javafx-8,javafx-bindings,Java,Javafx 8,Javafx Bindings,我是JavaFX新手,想知道BindingsAPI是否允许以更简单的方式实现以下内容。考虑一个模型,该模型包含一个可能是空的数据库(因为数据库异步加载)和一个显示标签“代码>状态< /代码>的视图,反映数据库的状态。如果为空,则应显示“加载…”之类的内容;如果不是空,则应显示数据库中有多少项。如果状态能够反映数据库在增长或收缩时的大小,那就太好了 到目前为止,我了解可以使用转换器将整数属性(数据库大小)绑定到标签的文本属性。这很好,但我希望标签显示的内容多于数字。类似“Loaded{0}item

我是JavaFX新手,想知道BindingsAPI是否允许以更简单的方式实现以下内容。考虑一个模型,该模型包含一个可能是空的数据库(因为数据库异步加载)和一个显示标签“代码>状态< /代码>的视图,反映数据库的状态。如果为空,则应显示“加载…”之类的内容;如果不是空,则应显示数据库中有多少项。如果状态能够反映数据库在增长或收缩时的大小,那就太好了

到目前为止,我了解可以使用转换器将整数属性(数据库大小)绑定到标签的文本属性。这很好,但我希望标签显示的内容多于数字。类似“Loaded{0}items”的本地化字符串。我们不要忘记数据库可能仍然是空的

这就是我的解决方案

@Override
public void initialize(URL url, ResourceBundle bundle) {
    // Initialize label with default value
    status();
    model.databaseProperty().addListener((obs, old, neu) -> {
        // Update label when database is no longer null
        status();
        // Update label when size of database changes
        neu.sizeProperty().addListener(x -> status());
    });
}

public void status() {
    if (model.database() == null) {
        status.setText(bundle.getString("status.loading"));
    } else {
        String text = bundle.getString("status.ready");
        int size = model.database().size();
        text = new MessageFormat(text).format(size);
        status.setText(text);
    }
}
这是可行的,但是有没有一种方法可以通过绑定链或者至少部分绑定来实现呢?我已经看到了布尔绑定的强大性(以及长度),但我不确定字符串绑定是否可以实现如此灵活的功能。

您可以使用它,它本质上是一种动态的if/then绑定:*

但是,上面假设
bundle.getString(“status.ready”)
返回java.util.Formatter字符串,而不是MessageFormat字符串。换句话说,它需要
“加载%,d项”
,而不是
“加载{0,number,integer}项”

绑定没有内置的对MessageFormat的支持,但是如果您真的想坚持使用MessageFormat(这是一个合法的要求,因为MessageFormat可以做一些格式化程序不能做的事情),您可以使用以下内容创建自定义绑定:


*实际上,它更像是三元
运算符。

回答得好,谢谢。据我所知,
select
只匹配
getSize()
方法,而不是
size()
方法,对吗?有什么方法可以改变这种行为吗?如果数据库类添加了一个
public IntegerProperty sizeProperty()
方法,那就足够了。如果无法向数据库类添加方法,则可以将Bindings.selectInteger替换为
Bindings.createIntegerBinding
,类似于createStringBinding的工作方式,但如果未将表示大小的一些可观察值传递给createIntegerBinding,当大小更改时,自定义绑定将不知道如何更新自身。经过进一步考虑,我意识到应该是
public ReadOnlyIntegerProperty sizeProperty()
。另外还有一种表示size属性的可能性,尽管这需要更多的努力:您可以为数据库类创建一个自定义Beaninfo,如中所述,告诉bean属性发现过程哪些方法对应于类的每个属性。这可能是某些属性所必需的。我现在被一个事实难住了,
select
根本无法匹配
sorted()
方法的
observeList
。具体来说,
select(object,“list”,“sorted”)
将引发异常,即使
object
有一个
listProperty()
getList()
方法。只需澄清一下,仍然可以进行
((observeblist)绑定。select(object,“list”).get().sorted()
但这有点冗长
status.textProperty().bind(
    Bindings.when(model.databaseProperty().isNull())
        .then(bundle.getString("status.loading"))
        .otherwise(
            Bindings.selectInteger(model.databaseProperty(), "size").asString(
                bundle.getString("status.ready")))
);
MessageFormat statusFormat = new MessageFormat(bundle.getString("status.ready"));

status.textProperty().bind(
    Bindings.when(model.databaseProperty().isNull())
        .then(bundle.getString("status.loading"))
        .otherwise(
            Bindings.createStringBinding(
                () -> statusFormat.format(new Object[] { model.getDatabase().getSize() }),
                model.databaseProperty(),
                Bindings.selectInteger(model.databaseProperty(), "size")))
);