JavaFX更新进度栏,等待线程完成 [英] JavaFX update progress bar and wait for threads to complete
问题描述
我正在尝试更新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.
推荐答案
请参阅下面的示例应用程序.它提供了一个简单的ProgressBar
和Label
来演示如何使用后台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()
andsetOnSucceeded()
methods.
这篇关于JavaFX更新进度栏,等待线程完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!