【问题标题】:Populate Tableview with super class fields使用超类字段填充 Tableview
【发布时间】:2020-06-17 17:48:31
【问题描述】:

我有几个类都继承自一个 super 类,需要填充与其类相关的几个 TableViews。

超类是抽象的,一些 getter 和 setter 是最终的,但仍包含填充单元格所需的数据。

为每一列编写一个新的回调类是可行的,但我正在寻找一种方法来实现这一点。

示例代码

class SuperClass
{
  protected String name;
  protected double value;
  public final void setName(String name)
  {
    this.name = name;
  }
  public final void getName()
  {
    return this.name;
  }
  public final void setValue(double value)
  {
    this.value = value;
  }
  public double getValue()
  {
    return this.value;
  }
}
class SubClass1 extends SuperClass
{
  private int id;
  public void setId(int id)
  {
    this.id = id;
  }
  public int getId()
  {
    return this.id;
  }
}
class SubClass2 extends SuperClass
{
  private String location;
  public void setLocation(String location)
  {
    this.location = location;
  }
}
class SubClass3 extends SuperClass
{
  private ObservableMap<SuperClass> map;
  public ObservableMap<SuperClass> map()
  {
    return this.map;
  }
}

表格视图

TableColumn<SubClass1, Integer> tc1_id;
TableColumn<SubClass1, String> tc1_name;
TableColumn<SubClass1, Double> tc1_value;
TableColumn<SubClass2, String> tc2_loc;
TableColumn<SubClass2, String> tc2_name;
TableColumn<SubClass2, Double> tc2_value;
TableColumn<SubClass3, String> tc3_name;
TableColumn<SubClass3, Double> tc3_value;

这是我将要做什么的参考... Accessing Subclass properties in a JavaFX TableView ObservableArrayList

但是仅使用示例代码,我基本上是重写了 2 个方法,每个方法 3 次......而且在实际程序中还有更多。 (稍微多一点)

【问题讨论】:

  • 您不能在同一个TableView 中使用所有这些列。 TableColumn&lt;S,T&gt; 只能添加到 TableView&lt;S&gt;,因此所有列的第一个类型参数必须相同。
  • tc1 指表 1 -> 列 X tc2 指表 2 -> 列 X tc3 指表 3 -> 列 X
  • 那么每个子类对应不同的表?在那种情况下,我不明白你在问什么。
  • 没错。 “几个 TableView”
  • 在此处解释您的问题(最好使用minimal reproducible example)并请使用 java 命名约定。请注意,此站点不是帮助台,而是社区努力构建知识库、不完整/含糊/不清楚的问题对这项工作没有帮助

标签: javafx java-8 callback tableview


【解决方案1】:

我认为您只是在问如何减少您必须编写的代码量。解决方案与任何此类问题相同:编写一个执行重复部分的方法,并使用变化的部分对其进行参数化。所以在这种情况下,您只需要编写一个通用实用程序方法来生成表格列,获取列的标题和生成单元格值工厂所需属性的函数。

例如你可以做类似的事情

private <S,T> TableColumn<S,T> createColumn(String title, Function<S, Property<T>> prop) {
    TableColumn<S,T> column = new TableColumn<>(title);
    column.setCellValueFactory(cellData -> prop.apply(cellData.getValue()));
    return column ;
}

如果您的模型类使用 JavaFX 属性,那么您只需要

TableColumn<SubClass1, Number> tc1Id = createColumn("Id", SubClass1::idProperty);

等等

如果您不使用 JavaFX 属性(这是推荐的方法),您仍然可以这样做

TableColumn<SubClass2, String> tc2Loc = 
    createColumn("Location", item -> new SimpleStringProperty(item.getLocation()));

或者只是创建一个接受Function&lt;S,T&gt; 而不是Function&lt;S,Property&lt;T&gt;&gt; 的方法。

【讨论】:

  • 在将 SuperClass 的字段转换为属性类型并添加方法 StringProperty nameProperty() 之后,我仍然对 TableView&lt;SuperClass&gt; table; TableColumn&lt;SuperClass, StringProperty&gt; tableColumn = createColumn("Name", SuperClass::nameProperty); table.setItems(ObservableList&lt;SuperClass&gt;); 有疑问,尽管我知道在您的第一个答案中您提到了一些关于无法拥有的问题TableView 中有多种类型的项目,但 TableColumns 仅从 SuperClass 引用 Properties
  • 具体是什么问题?
  • tableColumn.setCellValueFactory(PropertyValueFactory&lt;SuperClass, StringProperty&gt;("name"); generate TableColumn cannot be cast to javafx.scene.control.TableColumn$CellDataFeatures --- TableColumn&lt;SuperClass, StringProperty&gt; tableColumn = createColumn("name", SuperClass::nameProperty); won't compile " 不兼容的类型:推断的类型不符合等式约束(s )" --- SuperClass::nameProperty 的签名是 public final StringProperty nameProperty()
  • @DavidFisher 是的,因为它应该是TableColumn&lt;SuperClass, String&gt; tableColumn = createColumn(...);。对于TableColumn&lt;S,T&gt;,方法签名是setCellValueFactory(Callback&lt;CellDataFeatures&lt;S,T&gt;, ObservableValue&lt;T&gt;&gt;)。因此,如果您将T 设为StringProperty,您最终将不得不返回ObservableValue&lt;StringProperty&gt;,而不是当前返回的内容(StringProperty,它实现了ObservableValue&lt;String&gt;)。
  • 我不能拥有T extend Property 似乎很奇怪,但我想这可行
猜你喜欢
  • 1970-01-01
  • 2013-06-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-22
  • 2016-02-16
  • 2017-07-29
相关资源
最近更新 更多