【问题标题】:JavaFX8 TreeTableView notifications for scrolled items滚动项目的 JavaFX8 TreeTableView 通知
【发布时间】:2014-04-17 18:42:26
【问题描述】:

我正在编写一个使用 JavaFX8 TreeTableView 的应用程序。树形表有三列,其中两列是字符串属性(name 和 value),另一列有一个 Canvas 小部件,它从来自数据库(波形)。应用程序上还有一个控件,允许缩小或缩小(或左右滚动)显示(所有图纸)。

name 和 value 列使用来自我的数据模型的 StringProperty 值,因此为这些列设置了 CellValueFactory。绘图列同时使用 CellFactory 和 CellValueFactory,如下所示:

    // Waveform column
    TreeTableColumn<DrawRow, WaveformTraceBox> waveColumn = new TreeTableColumn<>();
    waveColumn.setCellFactory(new Callback<TreeTableColumn<DrawRow, WaveformTraceBox>, TreeTableCell<DrawRow, WaveformTraceBox>>() {
        @Override
        public TreeTableCell<DrawRow, WaveformTraceBox> call(TreeTableColumn<DrawRow, WaveformTraceBox> param) {
            return new WaveformTraceBoxTreeTableViewCell<>();
        }
    });
    waveColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<DrawRow, WaveformTraceBox>, ObservableValue<WaveformTraceBox>>() {
        @Override
        public ObservableValue<WaveformTraceBox> call(TreeTableColumn.CellDataFeatures<DrawRow, WaveformTraceBox> param) {
            return new ReadOnlyObjectWrapper<>(new WaveformTraceBox());
        }
    });

WaveformTraceBoxTreeTableViewCell 在哪里:

protected static class WaveformTraceBoxTreeTableViewCell<T> extends TreeTableCell<DrawRow, T> {

    public WaveformTraceBoxTreeTableViewCell() {
        super();
    }

    @Override
    protected void updateItem(T value, boolean empty) {
        super.updateItem(value, empty);
        setText(null);
        setGraphic(null);
        if (!empty && getTreeTableRow().getItem() != null) {
            getTreeTableRow().getItem().setTraceBox((WaveformTraceBox)value);
            setGraphic((WaveformTraceBox) value);
        }
    }

DrawRow 是我的数据模型。当用户通过窗口上的控件缩小或缩小时,绘制行模型将通知其关联的 Canvas 绘图项以重新绘制其显示。由于生成显示需要处理大量数据,因此显示的绘制可能需要一些时间。

现在我的问题是:当 TreeTableView 小部件滚动时,它会要求新的 Canvas 小部件——这些小部件与数据模型中的 DrawRow 项相关联。但是,列表中滚动到屏幕外的小部件将被树小部件丢弃。

我无法判断我正在使用的物品是否已被丢弃或不再使用。因此,代码所做的工作比它需要的要多得多,因为它试图绘制不再使用或显示的单元格。我认为最终这会因为垃圾收集而导致其他问题。

所以我真正的问题是如何判断一个单元格是否已被树表遗弃,以便我可以停止尝试更新它?对此的任何帮助将不胜感激。在我所做的各种网络搜索中,我无法在任何地方找到它。

【问题讨论】:

    标签: javafx-8 treetableview


    【解决方案1】:

    您需要在这里担心吗?什么仍然是“不再使用的绘图单元”?您是否在 WaveformTraceBox 的后台线程中运行某种更新?

    无论如何,你的结构很奇怪。

    首先,(不太重要)为什么您的WaveformTraceBoxTreeTableViewCell 是通用的?你当然想要

    protected static class WaveformTraceBoxTreeTableViewCell extends TreeTableCell<DrawRow, WaveformTraceBox>
    

    然后您可以将T 替换为WaveformTraceBox 并摆脱演员表等。

    第二:如果我理解正确的话,WaveformTraceBox 是某种自定义的Node 子类;即它是一个 UI 组件。单元格值工厂不应该真正返回 UI 组件 - 它应该返回要显示的数据。然后细胞工厂应该使用一些 UI 组件来显示数据。

    这样,您可以在单元实现中创建单个 WaveFormTraceBox,并更新它在 updateItem(...) 方法中显示的数据。

    比如:

    // Waveform column
    TreeTableColumn<DrawRow, WaveformData> waveColumn = new TreeTableColumn<>();
    waveColumn.setCellFactory(new Callback<TreeTableColumn<DrawRow, WaveformData>, TreeTableCell<DrawRow, WaveformData>>() {
        @Override
        public TreeTableCell<DrawRow, WaveformData> call(TreeTableColumn<DrawRow, WaveformData> param) {
            return new WaveformTraceBoxTreeTableViewCell();
        }
    });
    waveColumn.setCellValueFactory(new Callback<TreeTableColumn.CellDataFeatures<DrawRow, WaveformData>, ObservableValue<WaveformData>>() {
        @Override
        public ObservableValue<WaveformTraceBox> call(TreeTableColumn.CellDataFeatures<DrawRow, WaveformTraceBox> param) {
            return new ReadOnlyObjectWrapper<>(getDataToDisplayForItem(param.getValue()));
        }
    });
    
    
    
    protected static class WaveformTraceBoxTreeTableViewCell extends TreeTableCell<DrawRow, WaveFormData> {
    
        private WaveformTraceBox traceBox = new WaveformTraceBox();
    
        public WaveformTraceBoxTreeTableViewCell() {
            super();
        }
    
        @Override
        protected void updateItem(WaveFormData value, boolean empty) {
            super.updateItem(value, empty);
            setText(null);
            setGraphic(null);
            if (!empty && getTreeTableRow().getItem() != null) {
                traceBox.setData(value);
                setGraphic(traceBox);
            } else {
                setGraphic(null);
            }
        }
    }
    

    显然您需要定义 WaveFormData 类来封装WaveFormTraceBox 将显示的数据,并为WaveFormTraceBox 提供setData(WaveFormData) 方法。如果您正在使用任何需要清理的资源,则调用setData(...) 将表明该WaveformTraceBox 不再访问之前的数据。

    【讨论】:

    • 感谢帮助!我的 WaveformTraceBoxTreeTableViewCell 是通用的原因是因为我实际上也将它用于其他两列来做一些样式(我在发布它时删除了该代码)。无论如何,我能找到的所有示例(很少)在表格或树中都有小部件,似乎是在单元格值工厂中制作小部件,然后将其设置为单元格工厂中的图形。现在我明白我做错了什么。你可能会说我对这些东西很陌生,所以我有点得不偿失。感谢您的帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多