滚动时,JavaFX图标随机从TreeTableView中消失,性能也很慢 [英] JavaFX icons randomly disappear from TreeTableView when scrolling, performance slow as well

查看:231
本文介绍了滚动时,JavaFX图标随机从TreeTableView中消失,性能也很慢的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于某种原因,当我的TreeTableView填充了许多元素时,文件上设置的图标将随机变为完全透明。



向下滚动时,它们将刷新。



我已经检查了这个帖子:中记录报告以请求开发人员查看您在问题中发布的原始代码的性能(如果内部可以在平台代码中完成,以改进或记录其可扩展性,并使用大量树项图形集)。


For some reason, when my TreeTableView is populated with many elements, the icons set on the files will randomly turn completely transparent.

Upon scrolling down, they will refresh.

I've already checked this thread: JavaFX TreeTableView rows gone when scrolling

I assume since I'm on

java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b15)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)

This version I updated to literally 2-3 days ago after formatting, so I can't see the above version being 2+ years out of date (as the other thread I linked is that old [from 2013]).

A lot of the nodes are buried in other nodes that are not expanded, therefore I'm confused at why clicking on one of the nodes to expand them causes the GUI to chug slowly. When I click on one of the nodes, approximately 15 new elements appear. I don't have an old computer (2.8 Ghz 4 core 8 gig ram), unless such a thing is that taxing?

This is also happening to nodes that are already loaded, so scrolling up and back down will cause them to disappear.

Here is a small example, sometimes it can get ridiculous (I've had up to half of the images on a full screen go blank).

Is this a bug? Or am I doing something wrong? Was the TreeTableView designed to handle this many entries (~50k, but they are nested in each other so only at most 2000-3000 are showing at any given time)?

I have never had this happen when dealing with 100-500 entries, but people who will be using this application will likely be dealing with data that can grow to be much bigger (5000-10000 nested elements which likely will not be showing all at the same time).

The only workaround I can think of is viewing each node by itself, whereby I remove every other node from the table and only display the current one, but this would require a fair amount of reworking which I'd like to avoid if possible.

EDIT: As a note, I use multiple ImageView's for each, so it's not like the problems where someone tries to use one Node in their graph.

=====================================================================

Updated MCVE:

package application;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {
        try {
            FXMLLoader fxmlloader = new FXMLLoader(Main.class.getResource("Test.fxml"));
            AnchorPane root = fxmlloader.load();
            Scene scene = new Scene(root, 400, 400);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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

Controller:

package application;

import javafx.fxml.FXML;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeTableColumn;
import javafx.scene.control.TreeTableView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;

public class Controller {

    @FXML
    public AnchorPane rootPane;

    @FXML
    public TreeTableView<String> ttv;

    @FXML
    public TreeTableColumn<String, String> ttc;

    @FXML
    public void initialize() {      
        Image img = new Image("http://i.imgur.com/TEgfhOw.png");
        TreeItem<String> root = new TreeItem<>("Root item");
        TreeItem<String> ti;
        for (int a = 0; a < 50000; a++) {
            ti = new TreeItem<>(Integer.toString(a));
            ti.setGraphic(new ImageView(img));
            root.getChildren().add(ti);
        }
        ttv.setRoot(root);
    }
}

FXML file:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane fx:id="rootPane" prefHeight="400.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Controller">
   <children>
      <TreeTableView fx:id="ttv" prefHeight="300.0" prefWidth="300.0">
        <columns>
          <TreeTableColumn fx:id="ttc" prefWidth="195.0" text="C1" />
        </columns>
      </TreeTableView>
   </children>
</AnchorPane>

This is what happens when I pull the scroller down eventually (usually within 3-4 seconds of dragging it up and down):

Furthermore, the files randomly appear to rip instantly to the left when dragging down. INSTRUCTIONS:

  • Run the file

  • Expand the root node

  • Drag the scrollbar up and down, from top to bottom to make it happen quickly (at least it does for me)

解决方案

Suggested alternate approach

I suggest that, for your use-case, that you don't set a graphic on each TreeItem. Instead, set a graphic in the cell value factory for your tree cells.

When you set a graphic on each TreeItem, you create 50K graphic nodes. When you set a graphic in the cell factory, you only create a single graphic node for each of the visible cells (e.g. 11 graphic nodes for your sample).

Sample code

The code below does not exhibit the behavior your describe in your question and works fine for me:

package application;

import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.fxml.FXML;
import javafx.scene.control.*;
import javafx.scene.image.*;
import javafx.scene.layout.AnchorPane;
import javafx.util.Callback;

public class Controller {

    @FXML
    public AnchorPane rootPane;

    @FXML
    public TreeTableView<String> ttv;

    @FXML
    public TreeTableColumn<String, String> ttc;

    @FXML
    public void initialize() {      
        Image img = new Image("http://i.imgur.com/TEgfhOw.png");
        TreeItem<String> root = new TreeItem<>("Root item");
        TreeItem<String> ti;
        for (int a = 0; a < 50000; a++) {
            ti = new TreeItem<>(Integer.toString(a));
//            ti.setGraphic(new ImageView(img));
            root.getChildren().add(ti);
        }
        ttc.setCellValueFactory(param -> 
            new ReadOnlyObjectWrapper<>(param.getValue().getValue())
        );

        ttc.setCellFactory(new Callback<TreeTableColumn<String, String>, TreeTableCell<String, String>>() {
            @Override
            public TreeTableCell<String, String> call(TreeTableColumn<String, String> param) {
                return new TreeTableCell<String, String>() {
                    private ImageView imageView;

                    @Override
                    protected void updateItem(String item, boolean empty) {
                        super.updateItem(item, empty);

                        if (!empty && item != null) {
                            if (imageView == null) {
                                imageView = new ImageView(img);
                            }

                            setText(item);
                            setGraphic(imageView);
                        } else {
                            setText(null);
                            setGraphic(null);
                        }
                    }
                };
            }
        });

        ttv.setRoot(root);
    }
}

Even though the code in this answer will probably work for you, I still encourage you to log a report in the JavaFX issue tracker to request a developer to look into the performance of the original code you posted in your question (in case there is something internal which could be done in the platform code to improve or document its scalability with lots of tree item graphics set).

这篇关于滚动时,JavaFX图标随机从TreeTableView中消失,性能也很慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆