【问题标题】:(JavaFX) Unable to use controls when binding the textProperty()?(JavaFX) 绑定 textProperty() 时无法使用控件?
【发布时间】:2016-09-09 01:58:41
【问题描述】:

我刚刚开始学习属性绑定。我已经设置了控件并在此处绑定了属性(代码缩写):

@FXML
    private TextField txtOldPremium;
    @FXML
    private TextField txtNewPremium;
    @FXML
    private TextField txtProratedChange;

    private SimpleBooleanProperty quoteOnly = new SimpleBooleanProperty();
    private SimpleBooleanProperty reviewedBilling = new SimpleBooleanProperty();
    private SimpleStringProperty oldPremium = new SimpleStringProperty();
    private SimpleStringProperty newPremium = new SimpleStringProperty();
    private SimpleStringProperty proratedChange = new SimpleStringProperty();
    private SimpleStringProperty additionalInformation = new SimpleStringProperty();

    @FXML
    public void initialize() {

        // Bind the vehicle data to the tableview
        colEffectiveDate.setCellValueFactory(new PropertyValueFactory<Vehicle, String>("effectiveDateString"));
        colDescription.setCellValueFactory(new PropertyValueFactory<Vehicle, String>("description"));
        colVIN.setCellValueFactory(new PropertyValueFactory<Vehicle, String>("vin"));
        colAction.setCellValueFactory(new PropertyValueFactory<Vehicle, String>("action"));

        // Setup data binding to controls
        chkQuoteOnly.selectedProperty().bindBidirectional(quoteOnly);
        chkReviewedBilling.selectedProperty().bindBidirectional(reviewedBilling);
        txtOldPremium.textProperty().bindBidirectional(oldPremium);
        txtNewPremium.textProperty().bindBidirectional(newPremium);
    }

    @Override
    public String getComments() {
        StringBuilder comments = new StringBuilder();

        if (!txtOldPremium.getText().isEmpty() && !txtNewPremium.getText().isEmpty()) {

        } else {

            }
        }
        if (!txtProratedChange.getText().isEmpty()) {

        }

我在if (!txtOldPremium.getText().isEmpty() &amp;&amp; !txtNewPremium.getText().isEmpty()) { 收到 NullPointerException。我假设我在实现绑定方面做错了什么。 TextFields 本身目前是空的。

基本上,我只希望TextFieldoldPremium 字符串始终保持同步。但是我仍然需要能够对文本TextField 进行处理。我确实有几种其他类型的控件(CheckBoxComboBox 等)希望与基础数据同步。

【问题讨论】:

  • 什么是 null?
  • 事实证明,如果没有在其中输入文本,txtOldPremium.getText() 为 null。不过,我很好奇既然我已经绑定了属性,为什么会显示为 null。在绑定之前,txtOldPremium.getText().isEmpty() 只会返回 true。 (txtOldPremium 是对TextField 的引用)
  • 好吧,大概oldPremium,不管是什么,在你绑定时都包含null
  • 我将它们绑定在我的 FXML 控制器的 initialize() 方法中。这样做不合适吗?
  • 这与它有什么关系?显然,oldPremium.getValue() 在您执行bindBidirectional(...) 时返回null,因此当您执行绑定时,它会将文本字段的文本设置为null。您没有显示任何代码来显示您初始化oldPremium 的方式、时间或地点,甚至它是什么。

标签: java javafx data-binding


【解决方案1】:

您正在将文本字段的文本属性绑定到 StringProperty 实例,这些实例已在没有初始值的情况下创建。因此,例如,当您这样做时

private SimpleStringProperty oldPremium = new SimpleStringProperty();

您创建的oldPremium 没有实际值。所以oldPremium.getValue() 将返回null

那么当你这样做时

txtOldPremium.textProperty().bindBidirectional(oldPremium);

您同步两个属性(txtOldPremium.textProperty()oldPremium)的状态,这涉及将oldPremium(即null)的值复制到txtOldPremium.textProperty()

所以只需初始化属性以保存一个空字符串,而不是 null:

private SimpleStringProperty oldPremium = new SimpleStringProperty("");

等等

此外,请注意,在此特定示例中,您可以在不复制所有属性的情况下实现相同的目标。 IE。你可以这样做

private StringProperty oldPremium ;

// ...

@FXML
public void initialize() {

    // ...

    oldPremium = txtOldPremium.textProperty();

    // ...

}

您仍然可以定义属性访问器方法

public StringProperty oldPremiumProperty() {
    return oldPremium ;
}

public final String getOldPremium() {
    return oldPremiumProperty().get();
}

public final void setOldPremium(String oldPremium) {
    oldPremiumProperty().set(oldPremium);
}

正如您可能已经拥有的那样,它将具有完全相同的效果,但开销更少。

双向绑定对于同步属于两个不同对象的属性(例如,属于不同控制器或控制器和模型的属性)非常有用。也许您的问题减少了演示问题的代码,但我想我会为其他用户指出这一点。

【讨论】:

  • 谢谢。那成功了。我担心这样做会覆盖那些文本字段中已经存在的数据,但这并没有发生。
  • @Zephyr 是的,但请参阅更新。我看不出你的代码有什么意义。
  • 完全有可能我做事效率很低;我对 Java 还是很陌生。我想绑定属性以避免需要手动将 TextField 的任何更改保存回oldPremium 属性;调用 `getOldPremium()' 方法不会对 TextField 本身进行任何更改。
  • 在我所做的代码修改中,getOldPremium()oldPremiumProperty().get() 将始终在文本字段中显示值,但不会实例化一个全新的属性对象。同样,调用setOldPremium(...)oldPremiumProperty().set(...) 将自动更新文本字段。 (你甚至可以去掉引用oldPremium,直接让oldPremiumProperty()返回txtOldPremium.textProperty()。)
  • 我确实喜欢oldPremium = txtOldPremium.textProperty() 的简洁性,但我确实需要TextFieldoldPremium 更改时自动更新。就我而言,当oldPremium 和其他值已经用我希望在控件中填充的数据进行初始化时,我加载了 FXML。那是需要双向绑定的情况吗?
猜你喜欢
  • 2017-01-24
  • 1970-01-01
  • 2016-04-05
  • 1970-01-01
  • 1970-01-01
  • 2021-06-04
  • 1970-01-01
  • 1970-01-01
  • 2015-12-08
相关资源
最近更新 更多