我是JavaFX的新手,我想知道Bindings API是否允许一种更简单的方法来实现以下目标。考虑一个模型,该模型包含一个可能为空的数据库(因为该数据库是异步加载的)和一个显示标签status
的视图,该标签反映了数据库的状态。如果为null,则应显示“正在加载...”之类的信息;否则,应显示数据库中有多少项。如果状态可以反映数据库的大小(随着数据库的增大或缩小),那也将是很好的。
到目前为止,我知道我可以使用转换器将整数属性(数据库的大小)绑定到标签的text属性。很好,但是我希望标签显示的数字多于数字。一个精确的本地化字符串,例如“已加载{0}个项目”。而且,请不要忘记该数据库可能仍然为空。
这是我已有的解决方案
@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);
}
}
它可以工作,但是有没有办法用一连串的绑定或至少一部分绑定呢?我已经看到了布尔绑定有多么强大(和冗长),但是我不确定字符串绑定是否有可能具有灵活性。
答案 0 :(得分:0)
您可以使用Bindings.when,它本质上是动态的if / then绑定: *
status.textProperty().bind(
Bindings.when(model.databaseProperty().isNull())
.then(bundle.getString("status.loading"))
.otherwise(
Bindings.selectInteger(model.databaseProperty(), "size").asString(
bundle.getString("status.ready")))
);
但是,以上假设bundle.getString("status.ready")
返回的是java.util.Formatter字符串,而不是MessageFormat字符串。换句话说,它应该是"Loaded %,d items"
而不是"Loaded {0,number,integer} items"
。
绑定没有对MessageFormat的内置支持,但是如果您真的想坚持使用MessageFormat(这是一个合法的要求,因为MessageFormat可以做某些Formatter无法做的事情),则可以使用Bindings.createStringBinding:
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")))
);
*实际上,它更像是三元?
…:
运算符。