【问题标题】:JavaFX TableView: Do I HAVE to wrap my fields in Simple<Object/Integer/String>Property?JavaFX TableView:我必须将我的字段包装在 Simple<Object/Integer/String>Property 中吗?
【发布时间】:2014-06-16 05:18:25
【问题描述】:

我知道 TableView 及其列依赖于表示的对象具有 XYZProperty 值和适当的 getter 的事实。我必须使用所有这些符号吗?我的特定类有很多字段,并且也使用构建器模式。为什么我不能只使用原始字段变量而不是创建 XProperty 版本?

class ActionItem{
private String referenceNum;
private int percentComplete;
private ActionPlan actionPlans;
private LocalDate dateAssigned, dateDue, dateFinal, dateStarted,
     dateCompleted;
private String subject, description;
private Employee assignedBy, assignedToPrimary, assignedToSecondary;
private EmployeeGroup assignedToGroup;
private Criticality criticality;
private Status status;
----
private SimpleStringProperty referenceNumberProperty = new SimpleStringProperty();
private SimpleIntegerProperty percentCompleteProperty = new SimpleIntegerProperty();
private SimpleObjectProperty<ActionPlan> actionPlansProperty = new SimpleObjectProperty<ActionPlan>();
private SimpleObjectProperty<LocalDate> dateAssignedProperty = new SimpleObjectProperty<LocalDate>();
private SimpleObjectProperty<LocalDate> dateDueProperty = new SimpleObjectProperty<LocalDate>(),
     dateFinalProperty = new SimpleObjectProperty<LocalDate>(),
     dateStartedProperty = new SimpleObjectProperty<LocalDate>(),
     dateCompletedProperty = new SimpleObjectProperty<LocalDate>();
private SimpleStringProperty subjectProperty = new SimpleStringProperty(),
     descriptionProperty = new SimpleStringProperty();
private SimpleObjectProperty<Employee> assignedByProperty = new SimpleObjectProperty<Employee>(),
     assignedToPrimaryProperty = new SimpleObjectProperty<Employee>(),
     assignedToSecondaryProperty = new SimpleObjectProperty<Employee>();
private SimpleObjectProperty<EmployeeGroup> assignedToGroupProperty = new SimpleObjectProperty<EmployeeGroup>();
private SimpleObjectProperty<Criticality> criticalityProperty = new SimpleObjectProperty<ActionItem.Criticality>();
private SimpleObjectProperty<Status> statusProperty = new SimpleObjectProperty<ActionItem.Status>();
}

调用 getter 方法是否比尝试将对象从 SimpleProperty 中拉出更快?

【问题讨论】:

标签: java user-interface javafx tableview


【解决方案1】:

您几乎可以使用任何您喜欢的设计。

FX 属性模式为您提供了许多功能:它创建了可观察、可写的属性,在许多情况下可以直接连接到控件中。因此,如果您使用该模式设计您的“table beans”,那么您可以使用PropertyValueFactory 作为您的cellValueFactory,并且很多事情会“自动”发生,例如在值更改时更新表格单元格,反之亦然.

使用属性本身不会增加太多开销。有一个很好的 document 概述了使用 FX 属性的一些良好做法。

PropertyValueFactory,不过,我认为确实会增加一些开销,因为它依赖于反射来从指定的名称中查找属性。所以如果你更换,你会看到一些(我不保证有多少)好处

myTableColumn.setCellValueFactory(new PropertyValueFactory<>("thing"));

myTableColumn.setCellValueFactory(new Callback<CellDataFeatures<S,T>, ObservableValue<T>>() {
    public ObservableValue<T> call(CellDataFeatures<S,T> data) {
        return data.getValue().thingProperty() ;
    }
});

(或者,在 Java 8 中,更简单

myTableColumn.setCellValueFactory(data -> data.getValue().thingProperty());

)。

现在,如果您不需要 JavaFX 属性的花里胡哨(例如,表格行项目中的值不会在表格中编辑之外更改,并且表格中的编辑需要无论如何都要通过setOnCommit(...)“硬连线”),那么您可以通过省略JavaFX属性并仅使用常规Javabean模型以及getX()setX(...)方法来节省JavaFX属性的(小)开销。虽然我认为不多,但有一些性能优势,而且代码显然更少。

PropertyValueFactory 中反射的开销(我的猜测)大于使用 JavaFX 属性的开销,因此如果您出于性能原因希望这样做,我还将显式地将回调连接到 get方法,而不是依赖PropertyValueFactory。正如@brian 评论中的链接一样,一些以前的版本在实现它时效率很低(尽管现在已经修复了)。所以像

class Item {
  private String name ;
  public String getName() {
    return name ;
  }
  public void setName(String name) {
    this.name = name ;
  }
}

TableColumn<Item, String> nameCol = new TableColumn<>("Name");
nameCol.setCellValueFactory(itemData -> new ReadOnlyStringWrapper(itemData.getValue.getName()));

可能与它所获得的一样高效:同样,如果您希望您的表格可编辑,您需要手动将编辑提交连接到对setName(...) 的调用,并且不会更新表格外部的数据反映在表格中。

底线:如果您不想使用 JavaFX 属性,则不必这样做。您错过了一些免费功能,并且有一些方法可以自己编写代码,您可能会获得一些(轻微的)性能优势以及节省一些代码。真正难以解决的一种情况是从表格编辑外部更新表格中显示的属性。如果您在代码中这样做,JavaFX 属性会让您的生活更轻松。

更新: 根据您的 cmets,我建议您将 JavaFX 属性用于您的用例。我强烈建议阅读上面链接的document,幻灯片 18-46,尤其是幻灯片 30-43 上的属性模式。

但是,特别是,使用抽象类(例如StringProperty)作为属性的类型,而不是具体类型(SimpleStringProperty),并且当使用属性作为对象的属性时,使用名称和实例化它们参考他们的bean。例如:

private StringProperty referenceNumberProperty = new SimpleStringProperty(this, "referenceNumber");
public final StringProperty referenceNumberProperty() {
    return referenceNumberProperty ;
}
public final String getReferenceNumber() {
    return referenceNumberProperty.get() ;
}
public final void setReferenceNumber(String referenceNumber) {
    this.referenceNumberProperty.set(referenceNumber);
}

请注意,不将“property”作为参考名称的一部分(即private StringProperty referenceNumber 而不是private StringProperty referenceNumberProperty)稍微传统一点,但这当然完全取决于您。

【讨论】:

  • 我打算让表可编辑(它修改一个单例伪数据库),并显示从另一个窗口对数据库所做的任何更改。所以它确实需要双向。我想我会重写我的类,使它只使用 SimpleProperties。感谢您对开销的分析。此外,-> 运算符。什么给了?
  • -&gt;lambda expression,在 Java 8 中引入。
  • 对于您的用例,我绝对推荐使用 JavaFX 属性。我用一些关于使用它们的良好做法的注释更新了答案,并建议您阅读那里的链接。
猜你喜欢
  • 2016-11-13
  • 2018-08-18
  • 2021-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
  • 2013-06-05
  • 1970-01-01
相关资源
最近更新 更多