使用泛型构造 ObservableList
Using generic type to construct an ObservableList
我正在尝试扩展 JavaFX TableView class,这样我就可以将一个实体 class 传递给它,它会显示所有已保存的对象 class。我能够让它像这样工作,但我希望我的自定义 class 足够通用,只接受一个 Class 变量并处理其余的:
private void showSuppliers()
{
tabPane.getTabs().stream().filter((tab) -> (tab.getText().compareTo("Fournisseurs") == 0)).map((tab) -> (VBox)tab.getContent()).forEachOrdered((vBox) ->
{
TableView<Supplier> table = new TableView<>();
TableColumn nameColumn = new TableColumn("Nom");
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
TableColumn addressColumn = new TableColumn("Addresse");
addressColumn.setCellValueFactory(new PropertyValueFactory<>("address"));
TableColumn contactColumn = new TableColumn("Contact");
contactColumn.setCellValueFactory(new PropertyValueFactory<>("contactPerson"));
TableColumn phoneNumberColumn = new TableColumn("Téléphone");
phoneNumberColumn.setCellValueFactory(new PropertyValueFactory<>("phoneNumber"));
TableColumn emailColumn = new TableColumn("Courriel");
emailColumn.setCellValueFactory(new PropertyValueFactory<>("emailAddress"));
TableColumn creationDateColumn = new TableColumn("Date de création");
creationDateColumn.setCellValueFactory(new PropertyValueFactory<>("enteredDate"));
table.getColumns().addAll(nameColumn, addressColumn, contactColumn, phoneNumberColumn, emailColumn, creationDateColumn);
ObservableList<Supplier> suppliers = FXCollections.observableArrayList(supplierService.findAll());
table.setItems(suppliers);
vBox.getChildren().add(table);
});
}
同样,上述方法非常有效,但我必须对每个 table 列出我想避免的不同数据重复它。我的计划是使用通用类型扩展 TableView,如下所示:
public class EntityTable<T> extends TableView<T>
{
private final Class<T> entityClass;
public EntityTable(Class<T> entityClass)
{
this.entityClass = entityClass;
init();
}
private void init()
{
for (Field field : entityClass.getDeclaredFields())
{
if ((field.getType() != Set.class) && (field.getName().compareTo("id") != 0))
{
TableColumn column = new TableColumn(field.getName());
column.setCellValueFactory(new PropertyValueFactory<>(field.getName()));
getColumns().add(column);
}
}
}
}
如您所见,添加列不是问题。我不明白的是如何使用我的 T 来制作类似这样的 ObservableList :
ObservableList<Supplier> suppliers = FXCollections.observableArrayList(supplierService.findAll());
我尝试将 <Supplier>
替换为 <T>
或 <Class<T>>
,但这似乎无效。我在 Java 很久以前就知道这些东西几乎不存在,老实说,我在网上找到的有关它的信息有点令人困惑。
如何使用我的 T 变量作为类型来构造我的列表?
谢谢!
好吧,这很简单,我只是将其完全删除!这是最终结果,只需传递一个实体 class 和一个列表,table 会处理剩下的事情!
public class EntityTable<T> extends TableView<T>
{
private final Class<T> entityClass;
private final List<T> entityList;
public EntityTable(Class<T> entityClass, List<T> entityList)
{
this.entityClass = entityClass;
this.entityList = entityList;
init();
}
private void init()
{
for (Field field : entityClass.getDeclaredFields())
{
if ((field.getType() != Set.class) && (field.getName().compareTo("id") != 0))
{
TableColumn column = new TableColumn(field.getName());
column.setCellValueFactory(new PropertyValueFactory<>(field.getName()));
getColumns().add(column);
}
}
ObservableList list = FXCollections.observableArrayList(entityList);
setItems(list);
}
}
缺点是这将在 class 中显示带有实际 属性 名称的列 headers(并不总是非常用户友好)。欢迎任何自动将更好的内容放入 headers 列的建议!
编辑
对于我的列名,我最终创建了一个名为 FriendlyName 的自定义注释,它只有一个值参数。我现在像这样填充 headers 列:
FriendlyName friendlyName = field.getAnnotation(FriendlyName.class);
TableColumn column = new TableColumn(friendlyName.value());
我正在尝试扩展 JavaFX TableView class,这样我就可以将一个实体 class 传递给它,它会显示所有已保存的对象 class。我能够让它像这样工作,但我希望我的自定义 class 足够通用,只接受一个 Class 变量并处理其余的:
private void showSuppliers()
{
tabPane.getTabs().stream().filter((tab) -> (tab.getText().compareTo("Fournisseurs") == 0)).map((tab) -> (VBox)tab.getContent()).forEachOrdered((vBox) ->
{
TableView<Supplier> table = new TableView<>();
TableColumn nameColumn = new TableColumn("Nom");
nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
TableColumn addressColumn = new TableColumn("Addresse");
addressColumn.setCellValueFactory(new PropertyValueFactory<>("address"));
TableColumn contactColumn = new TableColumn("Contact");
contactColumn.setCellValueFactory(new PropertyValueFactory<>("contactPerson"));
TableColumn phoneNumberColumn = new TableColumn("Téléphone");
phoneNumberColumn.setCellValueFactory(new PropertyValueFactory<>("phoneNumber"));
TableColumn emailColumn = new TableColumn("Courriel");
emailColumn.setCellValueFactory(new PropertyValueFactory<>("emailAddress"));
TableColumn creationDateColumn = new TableColumn("Date de création");
creationDateColumn.setCellValueFactory(new PropertyValueFactory<>("enteredDate"));
table.getColumns().addAll(nameColumn, addressColumn, contactColumn, phoneNumberColumn, emailColumn, creationDateColumn);
ObservableList<Supplier> suppliers = FXCollections.observableArrayList(supplierService.findAll());
table.setItems(suppliers);
vBox.getChildren().add(table);
});
}
同样,上述方法非常有效,但我必须对每个 table 列出我想避免的不同数据重复它。我的计划是使用通用类型扩展 TableView,如下所示:
public class EntityTable<T> extends TableView<T>
{
private final Class<T> entityClass;
public EntityTable(Class<T> entityClass)
{
this.entityClass = entityClass;
init();
}
private void init()
{
for (Field field : entityClass.getDeclaredFields())
{
if ((field.getType() != Set.class) && (field.getName().compareTo("id") != 0))
{
TableColumn column = new TableColumn(field.getName());
column.setCellValueFactory(new PropertyValueFactory<>(field.getName()));
getColumns().add(column);
}
}
}
}
如您所见,添加列不是问题。我不明白的是如何使用我的 T 来制作类似这样的 ObservableList :
ObservableList<Supplier> suppliers = FXCollections.observableArrayList(supplierService.findAll());
我尝试将 <Supplier>
替换为 <T>
或 <Class<T>>
,但这似乎无效。我在 Java 很久以前就知道这些东西几乎不存在,老实说,我在网上找到的有关它的信息有点令人困惑。
如何使用我的 T 变量作为类型来构造我的列表?
谢谢!
好吧,这很简单,我只是将其完全删除!这是最终结果,只需传递一个实体 class 和一个列表,table 会处理剩下的事情!
public class EntityTable<T> extends TableView<T>
{
private final Class<T> entityClass;
private final List<T> entityList;
public EntityTable(Class<T> entityClass, List<T> entityList)
{
this.entityClass = entityClass;
this.entityList = entityList;
init();
}
private void init()
{
for (Field field : entityClass.getDeclaredFields())
{
if ((field.getType() != Set.class) && (field.getName().compareTo("id") != 0))
{
TableColumn column = new TableColumn(field.getName());
column.setCellValueFactory(new PropertyValueFactory<>(field.getName()));
getColumns().add(column);
}
}
ObservableList list = FXCollections.observableArrayList(entityList);
setItems(list);
}
}
缺点是这将在 class 中显示带有实际 属性 名称的列 headers(并不总是非常用户友好)。欢迎任何自动将更好的内容放入 headers 列的建议!
编辑
对于我的列名,我最终创建了一个名为 FriendlyName 的自定义注释,它只有一个值参数。我现在像这样填充 headers 列:
FriendlyName friendlyName = field.getAnnotation(FriendlyName.class);
TableColumn column = new TableColumn(friendlyName.value());