java - FXML 中的动态属性值?

标签 java javafx fxml

this JavaFX tutorial ,建议创建地址簿应用程序。已注册的人员可以被删除,但是在删除之前,必须在表格 View 中选择人员。

There will be an ArrayIndexOutOfBoundsException because it could not remove a person item at index -1. The index -1 was returned by getSelectedIndex() - which means that there was no selection.

To ignore such an error is not very nice, of course. We should let the user know that he/she must select a person before deleting. (Even better would be if we disabled the button so that the user doesn’t even have the chance to do something wrong.)

作者关于“如果我们禁用按钮就更好了……”的说法是完全正确的,但是他选择了第一种方式。我想,按钮状态的操作是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;
      }
  );
}

最佳答案

首先,我不确定以这种方式引用 boolean 字段是否会加载 FXML 文件(您没有具体说明它如何“不起作用”)。但忽略这一点,字段在 Java 中是不可观察的,这意味着更新字段不会自动导致 Buttondisable 属性被更新。这就是为什么 JavaFX 具有 [ReadOnly]Property 接口(interface)并引入“JavaFX Bean”(Java Bean 的扩展,添加了“属性” setter/getter ”);它允许观察者看到对象属性的变化。请注意,您可以 bind a writable propertyObservableValue 因此它始终具有相同的值。

现在,我预计会出现 expression binding将是您正在寻找的内容,但以下内容:

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

似乎不起作用 - 我遇到异常(使用 JavaFX 12.0.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}"/>

给出不同的异常:

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

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

<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));
    }

}

每当 selectedIndex 属性包含 时,isEqualTo 方法将返回值为 trueBooleanBinding -1。然后,disable 属性会绑定(bind)到此 BooleanBinding,因此它始终具有相同的值。您可以阅读Using JavaFX Properties and Binding了解更多信息。

关于java - FXML 中的动态属性值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55992915/

相关文章:

javafx-2 - Java FX 2 TreeView 模型引用

java - 如何引用资源文件夹中的 javafx fxml 文件?

java - 坐标序列的线条绘制错误

JavaFX 更改标签文本

java - 正则表达式在我的字符串中找不到最后一个单词

java - 多行文本到一张 map

java - 设置折线图绘图区域宽度

java - Spring Data Elasticsearch 找不到 geo_point 字段

java - 当 Android 手机连接到 PC 时,使 Java 应用程序同步 PC 上的联系人

`-fx-background-image` 更改时,JavaFX .setStyle(...) 不起作用