JavaFX 复杂字符串绑定
JavaFX complex string binding
我是 JavaFX 的新手,想知道绑定 API 是否允许更简单的方法来实现以下目标。考虑一个包含可能为空的数据库(因为数据库异步加载)和显示反映数据库状态的标签 status
的视图的模型。如果它是空的,它应该说类似 "Loading..." 的东西,如果不是,它应该显示数据库中有多少项目。如果状态可以反映数据库的大小随着它的增长或收缩,那就太好了。
到目前为止,我了解到我可以使用转换器将整数 属性(数据库的大小)绑定到标签的文本 属性。这很好,但我希望标签显示的不仅仅是数字。像 "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);
}
}
它可以工作,但是有没有一种方法可以通过绑定链或至少部分绑定来实现?我已经看到了布尔绑定的强大(和冗长),但我不确定字符串绑定是否可以实现如此灵活的功能。
可以使用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")
returns 是 java.util.Formatter 字符串,而不是 MessageFormat 字符串。换句话说,它需要 "Loaded %,d items"
而不是 "Loaded {0,number,integer} items"
.
Bindings 没有对 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")))
);
* 其实更像是三元运算符?
…:
.
我是 JavaFX 的新手,想知道绑定 API 是否允许更简单的方法来实现以下目标。考虑一个包含可能为空的数据库(因为数据库异步加载)和显示反映数据库状态的标签 status
的视图的模型。如果它是空的,它应该说类似 "Loading..." 的东西,如果不是,它应该显示数据库中有多少项目。如果状态可以反映数据库的大小随着它的增长或收缩,那就太好了。
到目前为止,我了解到我可以使用转换器将整数 属性(数据库的大小)绑定到标签的文本 属性。这很好,但我希望标签显示的不仅仅是数字。像 "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);
}
}
它可以工作,但是有没有一种方法可以通过绑定链或至少部分绑定来实现?我已经看到了布尔绑定的强大(和冗长),但我不确定字符串绑定是否可以实现如此灵活的功能。
可以使用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")
returns 是 java.util.Formatter 字符串,而不是 MessageFormat 字符串。换句话说,它需要 "Loaded %,d items"
而不是 "Loaded {0,number,integer} items"
.
Bindings 没有对 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")))
);
* 其实更像是三元运算符?
…:
.