【问题标题】:Is it possible to bind a TextProperty to an ObjectProperty's String attribute if it is not a String property?如果 TextProperty 不是 String 属性,是否可以将 TextProperty 绑定到 ObjectProperty 的 String 属性?
【发布时间】:2019-10-19 08:26:45
【问题描述】:

如何在不使用ChangeListener 的情况下将ObjectProperty 的属性(它本身不是属性)绑定到TextField 的文本属性等其他属性?

更具体地说:

我想让TextField 更改ObjectProperty 的属性。

示例代码:

地图DTO:

public class MapDTO {
    private String cityName;

    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }
}

地图管理器:

public class MapsManager {

    private static ObjectProperty<MapDTO> map = new SimpleObjectProperty<>();

    public static MapDTO getMap() {
        return map.get();
    }

    public static ObjectProperty<MapDTO> mapProperty() {
        return map;
    }

    public static void setMap(MapDTO map) {
        MapsManager.map.set(map);
    }
}

绑定测试控制器:

public class BindingTestController {

    private TextField cityNameTF = new TextField();

    private void initialize() {

        // Bind the cityName label to the selected MapsManager mapProperty's cityName   
        cityNameTF.textProperty().bind(Bindings.createStringBinding(
            () -> MapsManager.mapProperty().getValue() == null ? null :
                MapsManager.mapProperty().getValue().getCityName(),
            MapsManager.mapProperty()));
    }
}

我试过了:

从选定的值 String 属性创建一个字符串属性,但它没有成功,我无法找到正确的方法。

cityNameTF.textProperty().bindBidirectional(Bindings.createStringBinding(
() -> selectMapCB.getValue() == null ? null : selectMapCB.getValue().getCityName(), 
selectMapCB.valueProperty()));

从 mapProperty 的 String 属性创建一个字符串属性。

cityNameTF.textProperty().bindBidirectional(Bindings.createStringBinding(
() -> MapsManager.getMapProperty().getValue() == null ? null : MapsManager.mapProperty().getValue().getCityName(),
MapsManager.mapProperty()));

两个选项都给出相同的错误:

bindBidirectional (javafx.beans.property.Property<java.lang.String>)
in StringProperty cannot be applied to (javafx.beans.binding.StringBinding)

在这两种情况下,用bind 替换bindBidirectional 都可以,但是我无法更改TextField 中的文本。 我意识到这是因为我将TextField 的文本绑定到cityName 的字符串。所以我想以一种方式绑定它,但方向相反,比如:

MapsManager.mapProperty().????.bind(cityNameTF.textProperty());

但是“????” - 我没有 String 的属性,我不知道如何即时创建 StringBindingStringProperty

如何在ObjectProperty 的属性和另一个StringProperty 之间手动创建字符串绑定?

【问题讨论】:

  • 发布minimal reproducible example。这有点混乱:当您从问题的 GUI 部分开始时,我们不知道大多数对象是什么,而且您似乎正在使用一些第 3 方库。绑定不需要 GUI,因此如果您的问题是关于绑定的,请使用问题开头的纯数据结构。
  • @user1803551 我添加了 MapsManager 和 MapDTO 类。还有什么需要清理或添加的吗? (另外,将“JFXComboBox”和“JFXTextField”视为常规的“ComboBox”和“TextField”,没什么特别的)
  • 重复:你需要一些通知变化的东西......无论如何,时间 vor minimal reproducible example
  • @user1803551 完成。那个更好吗?另外,谢谢,我刚刚开始掌握正确提问的技巧。
  • 我尝试对 MCVE 提供一些帮助(尽管它仍然无法运行),它应该能更好地捕捉我认为您所要求的内容。基本上,重要的是你有一个对象,如果我理解正确的话,你想根据文本字段的text 属性(或相反?)更改其字段。在“我已尝试”部分,我假设 versionTFcityNameTF,如果是,请更改它。

标签: java javafx data-binding properties object-property


【解决方案1】:

您的MapDTO 基本上是JavaBean - 一个具有字段及其getter 和setter 的类。我们将把这样的字段称为bean 属性。由于您无法绑定到这些属性或从这些属性绑定,JavaFX 提供了将它们桥接到 JavaFX 属性的适配器。它们位于包中javafx.beans.property.adapter

提供各种类,充当常规 Java Bean 属性和相应 JavaFX 属性之间的适配器。

在内部,它们充当 bean 属性的包装器。

由于您的MapDTO 包含String,我们将使用JavaBeanStringProperty。请注意:

至少,Java Bean 类必须为属性实现 getter 和 setter。该类以及 getter 和 setter 方法必须声明为 public。

所以我们遵守要求。

我们使用它们的构建器创建这些适配器,在本例中为 JavaBeanStringPropertyBuilder

JavaBeanStringProperty cityNameProperty = JavaBeanStringPropertyBuilder.create()
                                              .bean(MapsManager.getMap())
                                              .name("cityName")
                                              .build();

构建器以反射方式访问数据。现在我们可以像往常一样使用创建的属性了:

cityNameProperty.bind(cityNameTF.textProperty());

对文本字段的text 属性的更改将更改MapDTO 实例中的cityName

【讨论】:

  • 按原样(假定的版本),它是 web 人员使用的 javabean - 对于 fx 绑定,如果 (java) bean 属性不触发 propertyChanges: without那些 fx 端无法在 (java) bean 端的更改上更新
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-30
  • 2011-01-01
  • 1970-01-01
相关资源
最近更新 更多