当前位置: 首页 > 知识库问答 >
问题:

JavaFX TableView:我必须在简单属性中包装我的字段吗?

蒙洛华
2023-03-14

我知道TableViews及其列取决于所表示的对象具有XYZProperty值和适当的getters这一事实。我一定要用这些符号吗?我的特定类有很多字段,并且也使用构建器模式。为什么我不能坚持使用原始字段变量,而不是创建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中拉出要快?

共有1个答案

孟翰海
2023-03-14

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

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

使用属性本身不会增加太多开销。有一个很好的文档概述了一些使用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() ;
    }
});

(或者,在Java8中,简单得多

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属性会让您的生活变得更加轻松。

更新:根据您的意见,我建议您使用JavaFX属性作为您的用例。我强烈建议阅读上面链接的文档,幻灯片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),这稍微有点传统,但当然这完全取决于您。

 类似资料:
  • 我们正试图在我们公司建立我们自己的表单-字段-组件。我们试图这样包装材料设计的组成部分: 字段: 文本框: 用法: 这大致会导致以下结果: 但是我在控制台中得到“mat-form-field必须包含一个MatFormFieldControl”。我想这与不直接包含matInput-field的mat-form-field有关。但它包含它,它只是在ng内容投影中。 这是一场闪电战:https://st

  • 问题内容: 我已经安装了Windows 7 x64,因此对于是否必须安装JDK x64或JDK x86感到困惑。请帮助我,谢谢 问题答案: 您应该安装x64,以便Java利用您的64位操作系统。

  • 我想将Oracle表映射到我创建的Java实体。在Oracle表中,我有: 称为数字(6,3)类型的字段 一个称为B的字段,类型为数字(6,0) 对于Java实体中与名为A的字段相对应的属性,我必须有一个BigDecimal(或者一个Float就足够了)?我必须有@列(精度=6,比例=2)? 我发现BigDecimal可能有点重,但如果有必要,我会使用它。将来我可能会使用这个实体为我的H2(DDL

  • 问题内容: 我使用的是用这样的: 我只关门了。我是否还需要关闭()? 问题答案: 不,您只需要关闭最外面的流。它将一直委托给包装的流。 但是,您的代码包含一个概念上的失败,应该在中发生关闭,否则当代码在打开和关闭之间引发异常时,它永远不会关闭。 例如 (请注意,我更改了代码以 引发 异常,以便您了解问题的原因,该异常即包含有关问题原因的详细信息) 或者,当您已经在使用Java 7时,也可以使用AR

  • 对于命令和 如果我是对的: 如果我想从packagist向我的项目添加库,我需要使用 我有一个项目,我不想将其发布到https://packagist.org/ 我只想在我的项目中添加一些库。 在运行之前,是否必须运行? 我看了一个教程,其中他们使用命令,然后调用,这让我很困惑,因为我认为与在Packagist上发布库有关。

  • 我正在处理Angular表单,我试图验证一个反应性表单。对于模板,我在项目中使用材料设计, 我在文本框中输入条件ngIf进行验证时出错 错误是-: ERROR错误:mat-form-field必须包含一个MatFormFieldControl。 请看-: 为了消除这个问题,我已经在文件2中导入了module.ts的MatInputMoules。已添加您必须将matInput添加到输入 但还是出现了