滚动时,JavaFX图标从TreeTableView中随机消失,性能也很慢

时间:2015-05-08 21:40:25

标签: java javafx

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

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

我已经检查了这个帖子:JavaFX TreeTableView rows gone when scrolling

我假设自从我开始

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)

我在格式化后的2-3天前更新了这个版本,所以我看不到上面的版本已经过时2年了(因为我链接的另一个帖子是[从2013年开始])。< / p>

许多节点都埋没在未扩展的其他节点中,因此我很困惑为什么单击其中一个节点来展开它们会导致GUI缓慢地突然显示。当我单击其中一个节点时,会出现大约15个新元素。我没有一台旧电脑(2.8 Ghz 4核8演出公羊),除非这样的事情要征税吗?

这也发生在已经加载的节点上,因此向上和向下滚动会导致它们消失。

这是一个小例子,有时它可能变得荒谬(我在全屏幕上最多有一半的图像变成空白)。

enter image description here

这是一个错误吗?或者我做错了什么? TreeTableView是否设计用于处理这么多条目(约50k,但它们彼此嵌套,因此在任何给定时间只显示2000-3000个)?

我在处理100-500个条目时从未发生过这种情况,但是将使用此应用程序的人可能会处理可能会变得更大的数据(5000-10000个嵌套元素可能同时显示所有内容。)

我能想到的唯一解决方法就是单独查看每个节点,从表中删除表中的每个其他节点,只显示当前节点,但这需要进行大量的重写,如果我想避免可能的。

编辑:作为一个注释,我为每个使用多个ImageView,所以它不像有人试图在图中使用一个Node的问题。

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

更新了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);
    }
}

控制器:

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文件:

<?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>

当我最终拉下卷轴时(通常在向上和向下拖动它的3-4秒内)会发生这种情况:

enter image description here

此外,文件随机显示在向下拖动时立即向左翻录。 说明:

  • 运行文件

  • 展开根节点

  • 向上和向下拖动滚动条,从上到下让它快速发生(至少对我而言)

2 个答案:

答案 0 :(得分:3)

建议的替代方法

对于您的用例,我建议您不要在每个TreeItem上设置图形。而是在树单元格的单元格值工厂中设置图形。

在每个TreeItem上设置图形时,可以创建50K图形节点。在单元工厂中设置图形时,只为每个可见单元格创建一个图形节点(例如,样本的11个图形节点)。

示例代码

以下代码未显示您在问题中描述的行为,并且对我有效:

$moduleName = Mage::app()->getRequest()->getModuleName();
$controllerName = Mage::app()->getRequest()->getControllerName();
$actionName = Mage::app()->getRequest()->getActionName();

即使此答案中的代码可能适合您,我仍然建议您在JavaFX issue tracker中记录报告,要求开发人员查看您在问题中发布的原始代码的效果(如果有一些内部可以在平台代码中完成,以改善或记录其可扩展性与大量的树项图形集。)

答案 1 :(得分:0)

@jewelsea的建议只能使用一个图标,但是当需要多个图标时会引起问题。

Image pink = new Image (getClass ().getResourceAsStream ("Letter-A-pink-icon.png"));
Image blue = new Image (getClass ().getResourceAsStream ("Letter-A-blue-icon.png"));

TreeItem<String> root = new TreeItem<> ("0");
for (int i = 1; i <= 5000; i++)
{
  TreeItem<String> ti = new TreeItem<> (Integer.toString (i));
  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> ()
        {
          ImageView imageView;

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

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

              int val = Integer.parseInt (item);
              imageView.setImage (val % 2 == 0 ? pink : blue);

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

ttv.setRoot (root);

}

Java正在重用TreeTableCells,这意味着ImageView每次都需要更新。