FXML中的动态属性值?

时间:2019-05-05 14:19:20

标签: java javafx fxml

this JavaFX tutorial中,建议创建通讯录应用程序。注册的人可以删除,但是在删除之前,必须在表视图中选择该人。

  

将出现ArrayIndexOutOfBoundsException,因为它无法   删除索引为-1的人员项目。索引-1由   getSelectedIndex()-这意味着没有选择。

     

当然,忽略这样的错误不是很好。我们应该让   用户知道他/她必须选择一个人才能删除。 (甚至   更好的是,如果我们禁用该按钮,以便用户   甚至有机会做错什么。)

作者完全正确,“最好是禁用按钮...”,但是他选择了第一种方法。我想,操作按钮状态是JavaFX应用程序开发的基本技能,因此我尝试实现更好的解决方案。

我们当然可以这样:

peopleTable.getSelectionModel().selectedItemProperty().addListener(
  (observable, oldValue, newValue) -> {

    showPersonDetails(newValue);

    boolean somebodySelected = peopleTable.getSelectionModel().getSelectedIndex() >= 0;
    button.setDisable(!somebodySelected);
  }
);

但是我对另一种方式感兴趣:对按钮使用动态属性值:

<Button
  mnemonicParsing="false"
  onAction="#handleDeletePerson"
  text="Delete"
  disable="disableDeleteButtonFlag"
/>

如果可以使用动态属性值,则不再需要显式调用button.setDisable()。但是,下面的代码不起作用。

@FXML
private boolean disableDeleteButtonFlag = true;

// ...


@FXML
private void initialize() {


  // ...

  peopleTable.getSelectionModel().selectedItemProperty().addListener(
      (observable, oldValue, newValue) -> {
        showPersonDetails(newValue);
        disableDeleteButtonFlag = peopleTable.getSelectionModel().getSelectedIndex() < 0;
      }
  );
}

1 个答案:

答案 0 :(得分:2)

首先,我不确定是否以这种方式引用boolean字段甚至可以加载FXML文件(您并未确切说明其“不起作用”的方式)。但忽略这一点,在Java中无法观察到字段,这意味着更新字段不会自动导致disable的{​​{1}}属性被更新。这就是JavaFX具有Button接口并引入“ JavaFX Bean ”(对 Java Bean 的扩展,其中添加了“属性获取器”)的原因。它使观察者可以看到对象属性的变化。请注意,您可以bind a writable property[ReadOnly]Property,因此它始终具有相同的值。

现在,我期望expression binding是您要寻找的东西,但以下内容:

ObservableValue

似乎不起作用,我遇到了一个异常(使用JavaFX 12.0.1):

<ListView fx:id="list"/>
<Button disable="${list.selectionModel.selectedIndex == -1}"/>

改为使用Caused by: java.lang.ClassCastException: class java.lang.Long cannot be cast to class java.lang.Integer (java.lang.Long and java.lang.Integer are in module java.base of loader 'bootstrap') at java.base/java.lang.Integer.compareTo(Integer.java:64) at javafx.fxml/com.sun.javafx.fxml.expression.Expression.lambda$equalTo$5(Expression.java:1105) at javafx.fxml/com.sun.javafx.fxml.expression.BinaryExpression.evaluate(BinaryExpression.java:55) at javafx.fxml/com.sun.javafx.fxml.expression.ExpressionValue.getValue(ExpressionValue.java:192) at javafx.base/com.sun.javafx.binding.ExpressionHelper.addListener(ExpressionHelper.java:53) at javafx.base/javafx.beans.value.ObservableValueBase.addListener(ObservableValueBase.java:55) at javafx.fxml/com.sun.javafx.fxml.expression.ExpressionValue.addListener(ExpressionValue.java:201) at javafx.base/javafx.beans.binding.BooleanBinding.bind(BooleanBinding.java:106) at javafx.base/javafx.beans.property.BooleanPropertyBase$ValueWrapper.<init>(BooleanPropertyBase.java:254) at javafx.base/javafx.beans.property.BooleanPropertyBase.bind(BooleanPropertyBase.java:168) at javafx.fxml/javafx.fxml.FXMLLoader$Element.processPropertyAttribute(FXMLLoader.java:326) at javafx.fxml/javafx.fxml.FXMLLoader$Element.processInstancePropertyAttributes(FXMLLoader.java:242) at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:775) at javafx.fxml/javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2838) at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2557) ... 17 more 属性:

selectedItem

给出另一个异常:

<Button disable="${list.selectionModel.selectedItem == null}"/>

由于这两个异常均来自JavaFX代码(即不是我们的代码),因此此行为可能是一个错误。那,或者我使用的表达式绑定不正确,在这种情况下,我希望有人能纠正我。由于尝试在FXML中绑定属性无效,因此解决方法是在代码中绑定属性。

Caused by: java.lang.NullPointerException
    at javafx.fxml/com.sun.javafx.fxml.expression.Expression.lambda$equalTo$5(Expression.java:1105)
    at javafx.fxml/com.sun.javafx.fxml.expression.BinaryExpression.evaluate(BinaryExpression.java:55)
    at javafx.fxml/com.sun.javafx.fxml.expression.ExpressionValue.getValue(ExpressionValue.java:192)
    at javafx.base/com.sun.javafx.binding.ExpressionHelper.addListener(ExpressionHelper.java:53)
    at javafx.base/javafx.beans.value.ObservableValueBase.addListener(ObservableValueBase.java:55)
    at javafx.fxml/com.sun.javafx.fxml.expression.ExpressionValue.addListener(ExpressionValue.java:201)
    at javafx.base/javafx.beans.binding.BooleanBinding.bind(BooleanBinding.java:106)
    at javafx.base/javafx.beans.property.BooleanPropertyBase$ValueWrapper.<init>(BooleanPropertyBase.java:254)
    at javafx.base/javafx.beans.property.BooleanPropertyBase.bind(BooleanPropertyBase.java:168)
    at javafx.fxml/javafx.fxml.FXMLLoader$Element.processPropertyAttribute(FXMLLoader.java:326)
    at javafx.fxml/javafx.fxml.FXMLLoader$Element.processInstancePropertyAttributes(FXMLLoader.java:242)
    at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:775)
    at javafx.fxml/javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2838)
    at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2557)
    ... 17 more
<VBox xmlns="http://javafx.com/" xmlns:fx="http://javafx.com/fxml" fx:controller="Controller">
    <ListView fx:id="list"/>
    <Button fx:id="button"/>
</VBox>

每当public class Controller { @FXML private ListView<YourType> list; @FXML private Button button; @FXML private void initialize() { button.disableProperty() .bind(list.getSelectionModel().selectedIndexProperty().isEqualTo(-1)); } } 属性包含isEqualTo时,BooleanBinding方法将返回一个值为true的{​​{1}}。然后,selectedIndex属性绑定到该-1,因此它始终具有相同的值。您可以阅读Using JavaFX Properties and Binding了解更多信息。