我正在尝试更新Java FX中的进度条。我的第一个问题是窗口说“不响应”,而不是实际更新。它只是冻结,然后在完成任务后,进度条就满了。因此我发现我必须使用多线程并像这样实现它。
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()。
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也发生了同样的事情。我不知道该怎么办。
答案 0 :(得分:3)
请参阅下面的示例应用程序。它提供了一个简单的$(".mobile-toggle").click(function() {
if ($(this).hasClass("inactive")) {
$(this).removeClass("inactive");
$(this).addClass("active");
//find current toggle element parent, then find next element(wrapper of the images) and finally find children image.
$(this).parent('.platform-toggle').next('.platform-images').children('.mobile-image').show();
$(this).siblings('.desktop-toggle').removeClass("active");
$(this).siblings('.desktop-toggle').addClass("inactive");
$(this).parent('.platform-toggle').next('.platform-images').children('.desktop-image').hide();
}
});
和一个ProgressBar
来演示如何使用后台Label
的进度更新UI。
代码也被注释。
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()
方法。