每个单元 JavaFX 的自定义单元工厂

问题描述 投票:0回答:1

我从几周开始就开始使用JavaFX,在花了很长时间处理

TableView
TreeTableView
之后,我来找你是为了更好地了解
cellFactory

我的第一个问题涉及 JavaFX 中

cellFactory
的全局方法。

通常工厂被设计为生产具有不同行为的不同对象。在 JavaFX 中,

cellFactory
似乎为整个列创建相同类型的
Cell

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

如果我想根据

Cell
的内容(值)更改
Cell
的行为,我不能(正如我到目前为止所看到的)。

所以我的第一个问题是:

如何根据单元格的内容为

cellFactory
中的每个
Cell
创建自定义
TableColumn

java design-patterns javafx cell factory
1个回答
2
投票

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

是的,确实如此。工厂模式的全部要点是允许使用它的类 (

TableView
) 创建遵守特定契约 (
TableCell
) 的类实例,但隐藏具体实现。

本页图表所示的工作流程:http://www.oodesign.com/factory-pattern.html

只需将

Client
替换为
TableView
,将
Product
替换为
TableCell
...

这允许为

cellFactory
cellValueFactory
设计可重用的类,而无需更改任何扩展
TableView
/
TableColumn
的内容。 (只需看一下
javafx.scene.control.cell
;其中的大多数(甚至所有)单元格都有一个静态方法来为其类型创建工厂;这些工作独立于
TableView
项目,并且可以一起使用,例如与
PropertyValueFactory
)。

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

你不知道。您编写一个表格单元格,根据通过修改

text
graphic
属性等传递的内容来决定其布局。当项目更改时(
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);
            }
        }
    }

});

这假设您可以根据给定的项目值决定布局。

如果您无法使用这种方法设计干净的代码,请考虑将其与策略模式结合起来,即让您的项目决定

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);
        }
    }

});
© www.soinside.com 2019 - 2024. All rights reserved.