JavaFX 表格 View : Do I HAVE to wrap my fields in Simple<Object/Integer/String>Property?

标签 java user-interface javafx tableview

我知道 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 中提取对象更快?

最佳答案

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

FX 属性模式为您提供了很多功能:它创建可观察、可写的属性,这些属性在许多情况下可以直接连接到控件中。因此,如果您使用该模式设计“表 bean”,那么您可以使用 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 模型来节省 JavaFX 属性的(小)开销,使用 getX()setX(...) 方法。虽然我认为没有太大的性能优势,但代码明显更少。

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(...) 的调用,并更新为表外部的数据不会反射(reflect)在表中。

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

更新: 根据您的评论,我建议您的用例使用 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);
}

请注意,不包含“属性”作为引用名称的一部分(即 private StringProperty referenceNumber 而不是 private StringProperty referenceNumberProperty)更为传统,但是当然这完全取决于你。

关于JavaFX 表格 View : Do I HAVE to wrap my fields in Simple<Object/Integer/String>Property?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23378725/

相关文章:

c# - 如何有条件地换出表单的 "User Input"部分?

javafx - RichTextFx中如何设置垂直滚动

java - 使用递归加分数 e=1+1/1!+1/2!+1/3!+

java - GridBagLayout 对齐文本字段吗?

java - 如何从ajax网页获取所有文本内容

JavaFX 对话 - 游戏

java - 哪个 Action 按钮可以在 JavaFX 中触发?

java - @WebFilter 需要 ServletComponentScan

python - 需要帮助运行 tkinter 程序

python-3.x - 如何在 PyQt 中更改 QCombobox 突出显示颜色