【问题标题】:JavaFX - TableView - Changes of field and fields of that fieldJavaFX - TableView - 该字段的字段和字段的更改
【发布时间】:2016-08-12 15:33:36
【问题描述】:

我处于以下情况。我有一个 TableView 填充了来自模型类 Foo 的数据:

public class Foo {
    private StringProperty someText;
    private Bar someObject;

    // getters, setters and properties dropped for clarity
}

这个类有一个Bar类型的字段:

public class Bar {
    private StringProperty someText;

    // getters, setters and properties dropped for clarity
}

其中一列必须显示来自Bar 的someText 的文本。所以我将该 StringProperty 绑定到该列。

但是当 Foo 中的整个 Bar 对象被另一个替换时,表格也应该更新。所以我在 Foo 中创建了一个包含 Bar 的 ObjectProperty,并将该属性绑定到列。当然,现在在Bar的someText里已经不听改了。

如何获得这些解决方案的“组合”,以便表格监听对象本身及其字段的变化?

【问题讨论】:

    标签: java javafx javafx-8


    【解决方案1】:

    只需使用 JavaFX API,您就可以做到

    TableColumn<Foo, String> barColumn = new TableColumn<>("Bar");
    
    barColumn.setCellValueFactory(cellData -> 
        Bindings.selectString(cellData.getValue().barProperty(), "someText"));
    

    出于几个原因,我不太喜欢 API 的那部分。首先,没有编译时检查:您只需将属性名称作为字符串提供,因此如果您有拼写错误,它只会在运行时显示。其次,如果foo.getBar() 返回null(它将在表格单元格中),这会向stderr 生成一堆警告。这些只是烦人(它们不会阻止任何东西的运行),而且真的不应该存在,因为根据 API 文档,这是一个受支持的用例。但是,它会起作用。


    要获得更健壮且更少遗留样式的实现,您可以使用 Tomas Mikula 的 ReactFX library,版本 2.0 或更高版本,其中包括对此类绑定的支持。使用那个库你会做的

    barColumns.setCellValueFactory(cellData -> 
        Val.flatMap(cellData.getValue().barProperty(), Bar::someTextProperty));
    

    这有编译时检查和类型检查等,没有虚假警告。

    【讨论】:

      【解决方案2】:

      您可以使用Bindings.select 通过多级层次结构选择值。这允许您创建单个 cellValueFactory 类:

      import java.util.Arrays;
      import javafx.beans.NamedArg;
      import javafx.beans.binding.Bindings;
      import javafx.beans.value.ObservableValue;
      import javafx.scene.control.TableColumn;
      import javafx.scene.control.cell.PropertyValueFactory;
      import javafx.util.Callback;
      
      public class NestedPropertyValueFactory<S, T> implements Callback<TableColumn.CellDataFeatures<S, T>, ObservableValue<T>> {
      
          private final String[] steps;
          private final PropertyValueFactory firstStepSelector;
      
          public NestedPropertyValueFactory(String... properties) {
              firstStepSelector = new PropertyValueFactory<>(properties[0]);
              this.steps = Arrays.copyOfRange(properties, 1, properties.length);
          }
      
          /**
           * @param property a string containing the names of the properties seperated
           * by '.'. (For easy use from fxml file)
           */
          public NestedPropertyValueFactory(@NamedArg("property") String property) {
              this(property.split("\\."));
          }
      
          @Override
          public ObservableValue<T> call(TableColumn.CellDataFeatures<S, T> param) {
              // use PropertyValueFactory for first step and Bindings.select for
              // additonal steps.
              return Bindings.select(firstStepSelector.call(param), steps);
          }
      
      }
      

      请注意,如果任何中间步骤产生null,您将在System.err 中收到警告。

      此外,对于此类,您需要使用符合命名约定的属性方法,即在这种情况下,方法的名称应为 someObjectPropertysomeTextProperty。这允许你使用类似于PropertyValueFactory的类:

      column.setCellValueFactory(new NestedPropertyValueFactory<>("someObject", "someText"));
      

      column.setCellValueFactory(new NestedPropertyValueFactory<>("someObject.someText"));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2021-03-09
        • 2023-03-07
        • 1970-01-01
        • 2021-05-17
        • 2017-09-26
        • 2018-07-13
        • 1970-01-01
        相关资源
        最近更新 更多