java - JavaFX的TableColumn的一些常用代码无法概括
问题描述
在JavaFX 的 TableView 的这个示例中, 3 个实例TableColumn
几乎都在做同样的事情。因此,我想编写一个新类SuperColumn extends TableColumn
来处理TableColumn
. 因此,我尝试将通用代码放在构造函数中,如下所示:
public class SuperColumn<Person, V> extends TableColumn<Person, V>{
String columnHead;
int columnWidth;
String variableName;
public SuperColumn(String columnHead, int columnWidth, String variableName) {
super();
this.setText(columnHead);
this.setMinWidth(columnWidth);
this.setCellValueFactory(new PropertyValueFactory<Person, V>(variableName));
this.setOnEditCommit(
new EventHandler<CellEditEvent<Person, V>>() {
@Override
public void handle(CellEditEvent<Person, V> t) {
((Person) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setEmail(t.getNewValue());
}
});
}
}
在上面,我想setEmail
依赖variableNew
. 也就是说,如果variableNew
是"setEmail"
,那么我们将调用setEmail(t.getNewValue())
。如果variableNew
是"setFirstName"
,那么我们将调用setFirstName(t.getNewValue())
。
我怎样才能做到这一点?
即使只是对于上面的代码,我也收到错误消息“方法 setEmail(V) 未为 Person 类型定义”。
解决方案
仅就一般编程风格而言,仅为了配置所创建实例的目的而对类进行子类化并不是特别好的做法,除非您提供了基类未提供的附加功能。如果子类除了有一个构造函数之外什么都不做,这是这个反模式的一个特定指标。我将在此处展示的一种更好的方法是使用某种创建模式,它可能与为您创建实例的一些静态方法一样简单。(更高级的实现将使用各种工厂模式。)
无论如何,你正在尝试做的一个版本,它不依赖于反射(我稍后会解释为什么我不喜欢反射方法)需要你传入某种处理新的函数(已编辑)特定Person
实例的值。ABiConsumer<Person, V>
适用于此:
public class TableColumns {
public static <V> TableColumn<Person,V> create(String columnHead, int columnWidth, String variableName, BiConsumer<Person, V> setter) {
TableColumn<Person, V> column = new TableColumn<>(columnHead);
column.setMinWidth(columnWidth);
column.setCellValueFactory(new PropertyValueFactory<>(variableName));
column.setOnEditCommit(t -> {
int row = t.getTablePosition().getRow();
Person person = t.getTableView().getItems().get(row);
V value = t.getNewValue();
setter.consume(person, value);
});
return column ;
}
}
您将使用它创建
TableColumn<Person, String> emailColumn =
TableColumns.create("Email", 100, "email", Person::setEmail)
请注意,您链接的示例并不是一个特别好的示例(即使它是 Oracle 的“官方”示例:它真的很老了)。使用 JavaFX 属性的模型类 ( Person
) 应该真正提供“属性访问器”方法:
public class Person {
private final StringProperty email = new SimpleStringProperty();
public StringProperty emailProperty() {
return email ;
}
public final String getEmail() {
return emailProperty().get();
}
public final void setEmail(String email) {
emailProperty().set(email);
}
// similarly for other properties
}
使用这个版本的Person
类,您的表列只需访问特定属性即可获取值(在 中cellValueFactory
)和设置值(在onEditCommit
处理程序中)。因此,您只需要一个为给定Person
实例提供属性的函数。您还可以轻松地将其概括为 type 的参数化行值S
:
public class TableColumns {
public static <S,T> TableColumn<S,T> create(String title, int width, Function<S, Property<T>> property) {
TableColumn<S,T> column = new TableColumn<>(title);
column.setMinWidth(width);
column.setCellValueFactory(cellData -> property.apply(cellData.getValue()));
column.setOnEditCommit(t -> {
int row = t.getTablePosition().getRow();
S rowValue = t.getTableView().getItems().get(row);
T value = t.getNewValue();
property.apply(rowValue).setValue(value);
});
return column ;
}
// other creational methods...
}
现在你做了
TableColumn<Person, String> emailColumn =
TableColumns.create("Email", 100, Person::emailProperty);
这种方法既避免直接使用反射,也避免使用遗留PropertyValueFactory
(在底层使用类似的基于反射的方法)。这里的主要好处是编译器现在将检查是否存在适当的方法,并在编译时捕获任何错误。(相比之下,当使用反射指定方法名称PropertyValueFactory
或 .
只是为了完整性,如果你真的想为此使用一个子类,它看起来像
public class SuperColumn<S,T> extends TableColumn<S,T> {
public SuperColumn(String title, int width, Function<S, Property<T>> property) {
super(title);
setMinWidth(width);
setCellValueFactory(cellData -> property.apply(cellData.getValue()));
setOnEditCommit(event -> {
int row = event.getTablePosition().getRow();
S rowValue = event.getTableView().getItems().get(row);
T value = event.getNewValue();
property.apply(rowValue).setValue(value);
});
}
}
但再次强调,这不是很好地使用继承,您应该更喜欢基于方法(或基于工厂)的方法。
推荐阅读
- php - 我需要帮助来显示 php oop 的时间
- kubernetes - 从 istio 虚拟服务创建 DNS 记录时出现外部 DNS 抛出错误
- flask - Flask:根据日期时间更改 Celery add_periodic_task 的频率
- image - 如何执行自动图像优化?
- java - 将变量转换为最后一个元素数组
- apache-flink - 有状态函数中的自定义指标
- flutter - 更新外部有状态小部件类的实例时如何更新屏幕
- sql - 如果表 1 中存在记录但表 2 中不存在记录,如何使用 CASE 显示特殊状态单元格?
- rust - 为什么间接级别允许省略“mut”?
- python - Python 中的问题 - AcloudguruDL