JavaFX更新进度栏,等待线程完成 [英] JavaFX update progress bar and wait for threads to complete

查看:246
本文介绍了JavaFX更新进度栏,等待线程完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试更新Java FX中的进度条.我的第一个问题是窗口说没有响应",而不是实际更新.它只是冻结,然后在完成任务后,进度条就满了.所以我发现我必须使用多线程并像这样实现它.

I'm trying to update a progress bar in Java FX. My first problem was that the window said "not responding" instead of actually updating. It just froze and then after the tasks were done, the progress bar became full. So I found out that I had to use multithreading and implemented it like this.

overallList.clear();
progressbar.setprogress(0);

for(Object obj : list) {
    class ThreadProgress implements Runnable { // inner class
        public void run() {
            thisList = scrape(obj);
            overallList.add(thisList);
            progressbar.setProgress(progressbar.getProgress() + (double)1/size);
        }
    }

    Thread current = new Thread(new ThreadProgress());
    current.start();
}

textAreaConsole.setText("Total number of things:" + overallList.size());

但是现在的问题是最后一行打印事物总数:0",因为线程在机器运行最后一行之前并没有真正完成执行.然后,我发现了多种解决方法,特别是使用join()或ExecutorService.我这样实现了join().

But now the problem is the final line prints "Total number of things: 0" because the threads don't actually finish executing before the machine runs the final line. Then I found out multiple ways to fix this, specifically using join() or ExecutorService. I implemented join() like this.

overallList.clear();
progressbar.setprogress(0);
List<Thread> threads = new ArrayList<Thread>();

for(Object obj : list) {
    class ThreadProgress implements Runnable { // inner class
        public void run() {
            thisList = scrape(obj);
            overallList.add(thisList);
            progressbar.setProgress(progressbar.getProgress() + (double)1/size);
        }
    }

    Thread current = new Thread(new ThreadProgress());
    current.start();
    threads.add(current);
}

for(Thread thread : threads) thread.join(); // with a try-catch loop

textAreaConsole.setText("Total number of things:" + overallList.size());

但是,这使我回到了最初的问题,窗口再次显示不响应". ExecutorService也发生了同样的事情.我不知道现在该怎么办.

But this brings me back to the original problem, the window says "not responding" again. Same thing happened with ExecutorService. I have no idea what to do now.

推荐答案

请参阅下面的示例应用程序.它提供了一个简单的ProgressBarLabel来演示如何使用后台Task的进度来更新UI.

See the example application below. It provides a simple ProgressBar and a Label to demonstrate how to update the UI with the progress of a background Task.

代码也被注释.

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class ProgressBarExample extends Application {

    // Create our ProgressBar
    private ProgressBar progressBar = new ProgressBar(0.0);

    // Create a label to show current progress %
    private Label lblProgress = new Label();

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

    @Override
    public void start(Stage primaryStage) {

        // Simple interface
        VBox root = new VBox(5);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        // Button to start the background task
        Button button = new Button("Start");
        button.setOnAction(event -> startProcess());

        // Add our controls to the scene
        root.getChildren().addAll(
                progressBar,
                new HBox(5) {{
                    setAlignment(Pos.CENTER);
                    getChildren().addAll(
                            new Label("Current Step:"),
                            lblProgress
                    );
                }},
                button
        );

        // Here we will

        // Show the Stage
        primaryStage.setWidth(300);
        primaryStage.setHeight(300);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    private void startProcess() {

        // Create a background Task
        Task<Void> task = new Task<Void>() {
            @Override
            protected Void call() throws Exception {

                // Set the total number of steps in our process
                int steps = 1000;

                // Simulate a long running task
                for (int i = 0; i < steps; i++) {

                    Thread.sleep(10); // Pause briefly

                    // Update our progress and message properties
                    updateProgress(i, steps);
                    updateMessage(String.valueOf(i));
                }
                return null;
            }
        };

        // This method allows us to handle any Exceptions thrown by the task
        task.setOnFailed(wse -> {
            wse.getSource().getException().printStackTrace();
        });

        // If the task completed successfully, perform other updates here
        task.setOnSucceeded(wse -> {
            System.out.println("Done!");
        });

        // Before starting our task, we need to bind our UI values to the properties on the task
        progressBar.progressProperty().bind(task.progressProperty());
        lblProgress.textProperty().bind(task.messageProperty());

        // Now, start the task on a background thread
        new Thread(task).start();
    }
}

:添加了setOnFailed()setOnSucceeded()方法.

Added the setOnFailed() and setOnSucceeded() methods.

这篇关于JavaFX更新进度栏,等待线程完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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