如何使用 javafx.beans.binding.Bindings.select(...) 进行简洁的值绑定
Posted
技术标签:
【中文标题】如何使用 javafx.beans.binding.Bindings.select(...) 进行简洁的值绑定【英文标题】:How to use javafx.beans.binding.Bindings.select(...) for concise value binding 【发布时间】:2012-04-07 09:08:22 【问题描述】:概述
作为一名有十年工作经验的 Swing 开发人员,我对 JavaFX 2.0 引入的特性感到非常兴奋,尤其是丰富、流畅、高级的数据绑定工具。仅此一项功能就值得学习新 API 的成本(自从放弃 FX 脚本以来,成本要低得多)。这将对我的模型/视图同步代码的可读性和可维护性产生直接影响。
到目前为止,我在第一级和基本派生绑定方面取得了巨大成功,但我正在努力找出将一个值绑定到数据图中两个或多个间接级别的值的“JavaFX 方式”。
问题
如下面的代码示例所示,我尝试使用javafx.beans.binding.Bindings.select()
将Label 的文本值与ComboBox 中当前选定项的包含属性之一同步。这段代码是我正在尝试做的更复杂的事情的一个简单示例,所以我知道使用较低级别的绑定 API 做到这一点并不难。我想知道是否可以使用更高级别的 fluent API,以及 select(...)
方法是否实际跟踪间接属性的更改(即,如果直接属性或选定的子属性发生更改,则更新属性)。
select(...)
上的文档和示例很少,所以我希望对此有高级经验的人可以告诉我,我是否正在尝试按设计使用 API,或者是否有其他方法可以使用级别绑定 API 来做我想做的事。
示例代码
这是演示代码。运行时,有一个包含两个项目的 ComboBox,然后是两个标签。第一个标签显示所选项目的toString()
版本。第二个标签尝试显示所选项目的属性之一,但仅显示null
。
import static javafx.beans.binding.Bindings.*;
import javafx.application.Application;
import javafx.beans.property.ReadOnlyStringProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.collections.FXCollections;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.Tooltip;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
/** Testing cascading binding change triggers. */
public class SandboxTest extends Application
public static void main(String[] args)
launch(args);
@Override
public void start(Stage stage) throws Exception
VBox root = new VBox(8);
root.setStyle("-fx-padding: 8;");
Scene s = new Scene(root);
stage.setWidth(200);
stage.setScene(s);
ComboBox<MoPoJo> list = new ComboBox<SandboxTest.MoPoJo>();
list.itemsProperty().set(FXCollections.observableArrayList(new MoPoJo("foo", "bar"), new MoPoJo("baz", "bat")));
Label direct = new Label();
direct.setTooltip(new Tooltip("Selected item to string"));
Label withSelect = new Label();
withSelect.setTooltip(new Tooltip("Second property of selected item"));
direct.textProperty().bind(convert(list.getSelectionModel().selectedItemProperty()));
withSelect.textProperty().bind(convert(select(list.getSelectionModel().selectedItemProperty(), "two")));
root.getChildren().addAll(list, direct, withSelect);
stage.show();
private static class MoPoJo
private StringProperty _one = new SimpleStringProperty();
private StringProperty _two = new SimpleStringProperty();
private StringProperty _name = new SimpleStringProperty();
public MoPoJo(String o, String t)
_one.set(o);
_two.set(t);
_name.bind(format(" %s, %s ", oneProperty(), twoProperty()));
public StringProperty oneProperty()
return _one;
public StringProperty twoProperty()
return _two;
public ReadOnlyStringProperty nameProperty()
return _name;
@Override
public String toString()
return nameProperty().get();
【问题讨论】:
【参考方案1】:Bindings.select
无法访问私有类。将MoPoJo
设为公共类,您的代码将正常工作。
public static class MoPoJo
P.S:我认为这个事实值得在文档中提及,所以我在 JavaFX javadoc 上提交了http://javafx-jira.kenai.com/browse/RT-20640。
【讨论】:
不知道我是否应该高兴答案如此简单!我在使用 JavaFX 2.0 绑定时遇到的最大问题是缺少错误报告/检测。我发现如果格式说明符不正确,Bindings.format(...)
会报告一些错误,但我没有发现错误报告在高级绑定中是一致的。如果有调试模式或回调 API 来追踪错误,那就太好了。感谢您提出问题!
Simeon,您可以为此提出功能请求。我发现使用调试模式进行绑定的想法也很棒。以上是关于如何使用 javafx.beans.binding.Bindings.select(...) 进行简洁的值绑定的主要内容,如果未能解决你的问题,请参考以下文章
如何在自动布局中使用约束标识符以及如何使用标识符更改约束? [迅速]