【问题标题】:Handling ScrollEvent on TableView takes too much of the CPU Time在 TableView 上处理 ScrollEvent 会占用过多的 CPU 时间
【发布时间】:2017-03-26 20:27:44
【问题描述】:

我有一个名为tableVerreTableView,我想让它的每一行都检查一个标准(stock 列值)并在滚动时对其执行一些代码,所以我编写了这段代码,但它使该程序消耗大量 CPU 时间,我不熟悉 Lambda 表达式,所以有没有更简单的方法来编写它? :

tableVerre.addEventFilter(ScrollEvent.ANY, new EventHandler<ScrollEvent>() {

    @Override
    public void handle(ScrollEvent scrollEvent) {

    stock.setCellFactory(column -> {

    return new TableCell<VerreFX, Number>() {
        @Override
        protected void updateItem(Number item, boolean empty) {
        super.updateItem(item, empty);

            TableRow<VerreFX> currentRow = getTableRow();

            if (empty || item == null) {
                setText("");
                setGraphic(null);
               currentRow.setStyle(tableVerre.getStyle());
            } else {
                setText(getItem().toString());
            }

            if (!isEmpty()) {
                if ((int) item == 0 && st.getVerresBOX()) currentRow.setStyle("-fx-background-color:lightcoral");
            }
        }
    };
});

            }
     });

【问题讨论】:

  • 为什么要替换滚动处理程序中的cellFactory?除非您调整表格的大小,否则可能甚至不会重新创建单元格...
  • 我会把它放在哪里?顺便说一下,在不调整表格大小的情况下重新创建单元格。
  • 如果您设置新的单元工厂 (AFAIK),将重新创建单元。如果您不不断地替换单元工厂,它们将在用户滚动时简单地重复使用(将在现有单元上调用 updateItem(...) 方法)。显然,简单地调用updateItem() 比重复替换所有单元格的性能要低得多。

标签: events javafx scroll event-handling tableview


【解决方案1】:

表格视图将在用户滚动时重用单元格,并在重用于新项目时自动在单元格上调用updateItem。所以你应该只设置一次单元工厂,然后让表格视图负责完成它设计的工作。如果您使用 FXML,则可以在 initialize() 方法中设置单元工厂,否则可以在创建表和列的任何位置设置。

您的单元格实现并不完全正确:因为一个单元格可能被重复使用以任意显示任何两个不同的项目,您需要考虑所有可能的条件。在您的实现中,如果一个单元格显示了 item.intValue()==0 的项目,然后被重用于显示 item.intValue() != 0 的项目,则样式将不会正确更新。

还请注意,您应该通过调用intValue()Number“转换”为int

TableColumn<VerreFX, Number> stock ;

// ...

stock.setCellFactory(column -> new TableCell<VerreFX, Number>() {
    @Override
    protected void updateItem(Number item, boolean empty) {
        super.updateItem(item, empty);

        TableRow<VerreFX> currentRow = getTableRow();

        if (empty || item == null) {
            setText("");
            setGraphic(null);
           currentRow.setStyle(tableVerre.getStyle());
        } else {
            setText(getItem().toString());
        }

        if (!isEmpty()) {
            if (item.intValue() == 0 && st.getVerresBOX()) {
                currentRow.setStyle("-fx-background-color:lightcoral");
            } else {
                currentRow.setStyle(tableVerre.getStyle());
            }
        }
    }
});

您应该能够完全删除滚动事件处理程序。

【讨论】:

  • 是的,我正在使用 fxml 并在 initialize() 中设置单元工厂正是我的方法,但是一旦一行更改样式,该行中显示的每个单元格都将采用相同的样式!没有更新自己。
  • 这是你提到的,但我没有那个错误!我曾经,并且我找到了一个解决方案(更新每个滚动事件上的单元格),它消耗 cpu 时间,这是问题中的代码,我找到了一种方法来防止滚动完成时更新单元格。谢谢詹姆斯
【解决方案2】:

首先,除了 CPU 时间之外,您并没有涵盖所有滚动情况,因为如果用户使用向下/向上键或使用滚动条滚动,则不会触发滚动事件。所以你必须再添加两个EventFilter,第一个将使用滚动条处理滚动。

tableVerre.addEventFilter(MouseEvent.MOUSE_CLICKED,(
            MouseEvent event)->
    {
        if ((event.getTarget() instanceof TableColumnHeader) | event.isDragDetect()) {
            System.err.println("Mouse Draged : " + event.toString());

            stock.setCellFactory((TableColumn<VerreFX, Number> column) -> {

                return new TableCell<VerreFX, Number>() {
                    @Override
                    protected void updateItem(Number item, boolean empty) {
                        super.updateItem(item, empty);

                        TableRow<VerreFX> currentRow = getTableRow();

                        if (empty || item == null) {
                            setText("");
                            setGraphic(null);
                            currentRow.setStyle(tableVerre.getStyle());
                        } else {
                            setText(getItem().toString());
                        }

                        if (!isEmpty()) {
                            if ((int) item == 0 && st.getVerresBOX()) {
                                currentRow.setStyle("-fx-background-color:lightcoral");
                            }
                        }
                    }
                };
            });
        }
    });

第二个将使用键盘的向下/向上键处理滚动。

tableVerre.addEventFilter(KeyEvent.KEY_PRESSED,new EventHandler<KeyEvent>(){
    @Override
    public void handle(KeyEvent event) {
        if (event.getCode() == KeyCode.DOWN | event.getCode() == KeyCode.UP) {
            stock.setCellFactory(column -> {

                return new TableCell<VerreFX, Number>() {
                    @Override
                    protected void updateItem(Number item, boolean empty) {
                        super.updateItem(item, empty);

                        TableRow<VerreFX> currentRow = getTableRow();

                        if (empty || item == null) {
                            setText("");
                            setGraphic(null);
                            currentRow.setStyle(tableVerre.getStyle());
                        } else {
                            setText(getItem().toString());
                        }

                        if (!isEmpty()) {
                            if ((int) item == 0 && st.getVerresBOX()) {
                                currentRow.setStyle("-fx-background-color:lightcoral");
                            }
                        }
                    }
                };
            });
        }
        System.err.println("Key Pressed : " + event.toString());
    }
});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-09-19
    • 1970-01-01
    • 2013-10-22
    • 1970-01-01
    • 1970-01-01
    • 2021-09-08
    • 1970-01-01
    相关资源
    最近更新 更多