每个单元格JavaFX的自定义单元格库

每个单元格JavaFX的自定义单元格库,java,design-patterns,javafx,cell,factory,Java,Design Patterns,Javafx,Cell,Factory,我在JavaFX工作了几周,在花了很长时间处理tableView和TreeTableView之后,我来到这里是为了更好地了解Cell-Factory 我的第一个问题涉及JavaFX中CellFactory的全局方法 通常情况下,工厂的设计是为了生产具有不同行为的不同对象。 但是,在JavaFX中,CellFactory似乎为整个列创建了相同类型的单元格 这种方法尊重工厂设计模式吗? 如果我想根据单元格的内容(值)改变单元格的行为,我不能(正如我到目前为止所看到的) 所以我的第一个问题是(鼓点…)

我在JavaFX工作了几周,在花了很长时间处理tableView和TreeTableView之后,我来到这里是为了更好地了解Cell-Factory

我的第一个问题涉及JavaFX中CellFactory的全局方法

通常情况下,工厂的设计是为了生产具有不同行为的不同对象。 但是,在JavaFX中,CellFactory似乎为整个列创建了相同类型的单元格

这种方法尊重工厂设计模式吗?

如果我想根据单元格的内容(值)改变单元格的行为,我不能(正如我到目前为止所看到的)

所以我的第一个问题是(鼓点…):

如何根据单元格内容为Tablecolumn中的每个单元格创建自定义单元格工厂?

这种方法对工厂设计模式的尊重是什么

是的。工厂模式的全部要点是允许使用它的类(
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);
        }
    }

});