JavaFX TableView 具有较大行数的滚动性能问题

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

我难住了。 我有一个用例,它涉及以 TableView 形式呈现任意大的分页表格结果集。

我发现,当我滚动到更大的行序号时,精细滚动(通过触摸手势或 TableView 上的鼠标滚轮)和粗略滚动(通过拖动滚动条滑块)都会退化为不可用。

降级发生在相对较小的行数(< ~1M). Note that the data model only ever holds a small subset of data at any given row offset and loads pages dynamically in response to scroll events.

我已将用例提炼为以下几行代码。 我过去能够毫无问题地支持类似的此类用例(大约 4 年前,10 亿行),所以我知道这是可行的。然而,无论现在的问题是什么,我都看不到它。

急需帮助...

顺便说一下,我已经尝试过使用具有相同效果的 SDK 和 JavaFX 的各种排列。

package com.example.demo;

import javafx.application.Application;
import javafx.beans.property.SimpleStringProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.ObservableListBase;
import javafx.scene.CacheHint;
import javafx.scene.Scene;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

import java.util.ArrayList;
import java.util.List;

public class Main extends Application {

    public static void main(String[] args) {
        launch();
    }

    @Override
    public void start(Stage stage) {
        final TableView<Row> table = new TableView();
        final BorderPane borderPane = new BorderPane();
        final Scene scene = new Scene(borderPane, 800, 600);

        TableColumn<Row, String> col = new TableColumn<>("row");
        col.setCellValueFactory(p -> new SimpleStringProperty(p.getValue().data[0].toString()));
        col.setPrefWidth(100);
        table.getColumns().add(col);

        col = new TableColumn<>("A");
        col.setCellValueFactory(p -> new SimpleStringProperty(p.getValue().data[1].toString()));
        col.setPrefWidth(100);
        table.getColumns().add(col);

        col = new TableColumn<>("B");
        col.setCellValueFactory(p -> new SimpleStringProperty(p.getValue().data[2].toString()));
        col.setPrefWidth(100);
        table.getColumns().add(col);

        col = new TableColumn<>("C");
        col.setCellValueFactory(p -> new SimpleStringProperty(p.getValue().data[3].toString()));
        col.setPrefWidth(100);
        table.getColumns().add(col);

        table.setCache(true);
        table.setEditable(false);
        table.setCacheHint(CacheHint.SPEED);

        table.setItems(getModel(10_000_000));

        borderPane.setCenter(table);
        stage.setScene(scene);

        stage.show();
    }

    private static ObservableList<Row> getModel(final int rowCount) {
        final List<Row> data = new ArrayList<>(rowCount);
        for (int x = 0; x < rowCount; x++) {
            data.add(new Row(x, new Object[] {x, "a_" + x, "b_" + x, "c_" + x }));
        }
        return FXCollections.unmodifiableObservableList(FXCollections.observableList(data));
    }

    private static final class Row {
        public final int rowOrdinal;
        public final Object[] data;

        public Row(final int rowOrdinal, final Object[] data) {
            this.rowOrdinal = rowOrdinal;
            this.data = data;
        }

        @Override
        public boolean equals(Object o) {
            return o != null && o.getClass() == Row.class && ((Row)o).rowOrdinal == rowOrdinal;
        }
        
        @Override
        public int hashCode() {
            return rowOrdinal;
        }
    }
}
java javafx tableview
1个回答
1
投票

是否出现性能倒退?

是的。

我在 OpenJDK 20 + JavaFX 20 OS X x64 13.2.1、2020 MacBook Pro 上运行了示例。对于大量行(例如 1,000,000+),通过滚动条用鼠标滚动时性能很慢。 1000 行,滚动性能很好。

使用 OpenJDK 8b251 时,10,000,000 行的滚动性能很快。

您不妨考虑提交错误报告

解决方法

使用 8 到 17 之间的 JavaFX 版本。从我的本地测试来看,具有大数据集的 TableView 的滚动表现可以接受。

对于其他 JavaFX 版本,您可以搜索在大型数据集支持下提高 TableView 性能的解决方法,但我不建议您这样做,除非您技术娴熟并且有动力这样做。相反,如果需要的 JavaFX 版本会出现此性能问题,请重新设计您的 UI 和逻辑,以免将大量项目加载到

TableView
后备列表中。也许,将最大项目数限制在 10,000 左右,并通过 pagination 处理大量数据。

知道这是什么时候开始的吗?

大型数据集的主要 TableView 滚动性能问题始于 JavaFX 版本 18。

对于我提到的 JDK 8b251 版本,1,000 行或 10,000,000 行的滚动性能是相同的(优秀)。

对于 JavaFX 17.0.2 版本(在 OS X x64 13.2.1、OpenJDK 20 上),10,000,000 行的滚动性能会略有卡顿,但总体来说还好。性能比 1,000 行的良好性能差一点,但不是真正的问题。

对于 JavaFX 18.0.2、19.0.2.1 和 20 版本(在 OS X x64 13.2.1、OpenJDK 20 上),10,000,000 行的滚动性能会非常卡顿,但并不好。性能比 1,000 行的良好性能差得多。

这些结果来自我环境中本地测试的主观视觉观察。您在您的环境中进行测试的结果和主观观察可能会有所不同,但大体上可能是相似的。

© www.soinside.com 2019 - 2024. All rights reserved.