每个单元格JavaFX的自定义单元格库
我在JavaFX工作了几周,在花了很长时间处理tableView和TreeTableView之后,我来到这里是为了更好地了解Cell-Factory 我的第一个问题涉及JavaFX中CellFactory的全局方法 通常情况下,工厂的设计是为了生产具有不同行为的不同对象。 但是,在JavaFX中,CellFactory似乎为整个列创建了相同类型的单元格 这种方法尊重工厂设计模式吗? 如果我想根据单元格的内容(值)改变单元格的行为,我不能(正如我到目前为止所看到的) 所以我的第一个问题是(鼓点…): 如何根据单元格内容为Tablecolumn中的每个单元格创建自定义单元格工厂? 这种方法对工厂设计模式的尊重是什么 是的。工厂模式的全部要点是允许使用它的类(每个单元格JavaFX的自定义单元格库,java,design-patterns,javafx,cell,factory,Java,Design Patterns,Javafx,Cell,Factory,我在JavaFX工作了几周,在花了很长时间处理tableView和TreeTableView之后,我来到这里是为了更好地了解Cell-Factory 我的第一个问题涉及JavaFX中CellFactory的全局方法 通常情况下,工厂的设计是为了生产具有不同行为的不同对象。 但是,在JavaFX中,CellFactory似乎为整个列创建了相同类型的单元格 这种方法尊重工厂设计模式吗? 如果我想根据单元格的内容(值)改变单元格的行为,我不能(正如我到目前为止所看到的) 所以我的第一个问题是(鼓点…)
TableView
)创建遵守特定契约(TableCell
)的类实例,但对其隐藏具体实现
本页图表中显示的工作流:
只需将Client
替换为TableView
,将Product
替换为TableCell
这允许为cellFactory
和cellValueFactory
设计可重用类,而无需更改任何扩展TableView
/TableColumn
。(只需看一下;其中的大多数(甚至所有)单元格都有一个静态方法来为其类型创建工厂;这些工作独立于TableView
项,并且可以与PropertyValueFactory
一起使用)
如何根据单元格的内容为TableColumn中的每个单元格创建自定义单元格工厂
你没有。您可以编写一个表格单元格,该单元格根据通过修改文本
和图形
属性等传递的内容来决定其布局。当项目更改时(item
属性侦听器或updateItem
方法)
通过显示使用默认构造函数创建的实例来显示类的单元格示例:
column1.setCellFactory(v -> new TableCell<Class<? extends Node>, Class<? extends Node>>() {
@Override
protected void updateItem(Class<? extends Node> item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
} else {
try {
setGraphic(item.getConstructor().newInstance());
} catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | InvocationTargetException ex) {
setGraphic(null);
}
}
}
});
//当然,内容可能更复杂
TableView tv=新的TableView(FXCollections.observableArrayList(
单元格->{
cell.setText(null);
setGraphic(新矩形(100100));
},
单元格->{
cell.setGraphic(空);
cell.setText(“你好,世界!”);
},
单元格->{
单元格设置图(新圆圈(20));
cell.setText(“圆”);
}));
TableColumn column1=新的TableColumn(“a”);
column1.setCellValueFactory(c->Bindings.createObjectBinding(()->c.getValue());
列1.setCellFactory(v->new TableCell(){
@凌驾
受保护的void updateItem(TableCellLayouter项,布尔值为空){
super.updateItem(项,空);
if(空){
设置图形(空);
setText(空);
}否则{
项目.布局单元(本);
}
}
});
OK,如果我理解正确,更改工厂不是解决方案,但在更新时将更改应用到单元格()方法是唯一的方法。在我的例子中,我只在单元格中显示文本,但编辑行为必须根据单元格中对象的类型而有所不同o我必须在编辑不同单元格时以不同的行为生成不同的文本字段,并且我必须在startEdit()上定义它,不是吗?@Doremus:是的,单元格可以重复使用以提高效率,但你可以在工厂中决定,使用哪个单元格类,或者是否以某种方式修改了单元格。updateItem
方法不是唯一的方法。如果您需要根据先前在cell.tks中显示的回复@fabian!撤销更改,那么将侦听器注册到cell的也可以工作,并且可能是有益的!最后一个问题,这个关于item属性的侦听器,我在哪里定义它?在我的定制手机工厂?在我初始化tableview的类中?@Doremus:在单元工厂或自定义的TableCell
类中。我在这里发布了一个在TableCell
的匿名子类中使用初始值设定项的示例:。在那个例子中,我已经将TableCell
子类化,添加了一个ComboBox
,但是如果您不需要它,您当然可以将它编写为cell factory:v->{TableCell c=new TableCell();c.itemProperty().addListener(…);return c;}
@Doremus:我刚刚注意到我不需要在链接的答案中对TableCell
进行子类化,并更改了代码。您仍然可以在这里查看以前的版本:(但我认为您不必这样做就可以了解要点)
@FunctionalInterface
public interface TableCellLayouter {
void layoutCell(TableCell<?, ?> cell);
}
// the content could be more complex of course
TableView<TableCellLayouter> tv = new TableView<>(FXCollections.observableArrayList(
cell -> {
cell.setText(null);
cell.setGraphic(new Rectangle(100, 100));
},
cell -> {
cell.setGraphic(null);
cell.setText("Hello world!");
},
cell -> {
cell.setGraphic(new Circle(20));
cell.setText("circle");
}));
TableColumn<TableCellLayouter, TableCellLayouter> column1 = new TableColumn<>("a");
column1.setCellValueFactory(c -> Bindings.createObjectBinding(() -> c.getValue()));
column1.setCellFactory(v -> new TableCell<TableCellLayouter, TableCellLayouter>() {
@Override
protected void updateItem(TableCellLayouter item, boolean empty) {
super.updateItem(item, empty);
if (empty) {
setGraphic(null);
setText(null);
} else {
item.layoutCell(this);
}
}
});