【问题标题】:Display ProgressBar while dynamically loading GridPane动态加载 GridPane 时显示 ProgressBar
【发布时间】:2018-11-14 12:53:38
【问题描述】:

嘿哟,

所以我目前正在开发一个 JavaFX 项目,而另一个 Java 项目正在处理/提供该项目的数据。

虽然我的大部分工作都在工作,但我仍在尝试在从数据项目加载数据时加载 ProgressBar,但我遇到了一些问题。

目前,我正在遍历数据,为每个“条目”创建/添加标签到 GridPane。在它上面,我声明了一个 JavaFX ProgressBar 并将它添加到我的“根包装器”VBox

            GridPane wrapper = new GridPane();
            ProgressBar progress = new ProgressBar();    
            viewBox.getChildren().add(progress);           

            int currentRow = 1;     
            for(Map.Entry<String, List<Observation>> item : handler.get(from, to).entrySet()) {                    
                if(item != null) {
                    for(Observation inner : item.getValue()) {
                        if(inner != null) {
                            // Add the data for the datalist
                            wrapper.add(new Label(item.getKey()), 0, currentRow);
                            wrapper.add(new Label(inner.getDate().toString()), 1, currentRow);
                            wrapper.add(new Label(String.valueOf(inner.getValue())), 2, currentRow);

                            currentRow++;
                        }
                    }
                }
            }

            viewBox.getChildren().add(wrapper);

现在,我已经尝试实现这一目标,因为我意识到仅此代码不会做太多事情:

1) 尝试将 GridPane 包装在 Task 中并从所述任务创建一个新线程 - 由于尝试创建 JavaFX 元素而不是在 JavaFX 应用程序线程中而无法正常工作

2) 尝试将所有 wrapper.add(new Label(...)); 包装在 Platform.runLater() 中 - 因为 wrapper 不是最终的,需要在范围内和范围外都存在,这也不起作用。

3) 尝试将数据条目逐个添加到临时映射中,并通过让 ProgressBar 部分在其自己的任务/线程中运行以这种方式显示进度。似乎只要我之后使用Thread.join(); 就可以工作,但似乎非常无效。

与往常一样,我们非常感谢任何和所有帮助。如果我忘记提及能够说出发生了什么所需的事情,请告诉我!我已尝试包含所有相关内容。

提前致谢!

【问题讨论】:

  • 如果我理解正确,您想在每次加载“数据”时更新进度条吗?您还应该显示上面的代码是否在应用程序线程上。
  • 我想要一个在第 6 行的循环完成时加载并“完成”的进度条,我猜这是一种表达方式。代码 sn -p 当前都在应用程序线程中。 @安德烈亚斯
  • 关于“1)”,只有少数JavaFX GUI对象必须在FX线程上创建;大多数对象都能够在任何单个线程上创建修改(只要它们不是场景图的一部分)。

标签: java multithreading javafx


【解决方案1】:

在您创建进度条并显示在您的 GUI 使用之后

progress.setProgress(double value)

具有适当的值,具体取决于您的进度。

例如,您可以将进度如下:

progress.setProgress((currentRow - 1) / handler.get(from, to).entrySet().size())

这一行可以作为你的 for 循环的第一行。完成整个作业后,将进度设置为 1 或移除进度条。

【讨论】:

  • 似乎工作正常,但似乎也有一些其他意外错误。不过,回答问题,所以我会将其标记为答案!谢谢!
【解决方案2】:

可以在任何线程中创建节点,但不能将它们从后台线程添加到场景中。您也不应该从后台线程更新场景中节点的属性。

GridPane wrapper = new GridPane();
ProgressBar progress = new ProgressBar();
viewBox.getChildren().add(progress);
viewBox.getChildren().add(wrapper);

new Thread(() -> {
    Collection<Map.Entry<String, List<Observation>>> entries = handler.get(from, to).entrySet();
    final double totalEntries = entries.size();
    int currentRow = 1; 
    for(Map.Entry<String, List<Observation>> item : entries) {                    
        if(item != null) {
            for(Observation inner : item.getValue()) {
                if(inner != null) {
                    // Add the data for the datalist
                    final Node[] nds = new Node[] {
                        new Label(item.getKey()),
                        new Label(inner.getDate().toString()),
                        new Label(new Label(String.valueOf(inner.getValue())))
                    };
                    final double newProgress = currentRow / totalEntries;
                    final int r = currentRow;
                    Platform.runLater(() -> {
                        wrapper.addRow(r, nds);
                        progress.setProgress(newProgress);
                    });
                    currentRow++;
                }
            }
        }
    }

}).start();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-17
    • 2019-10-10
    • 2012-11-19
    • 1970-01-01
    相关资源
    最近更新 更多