Multithreading 如何在JavaFX中从单独的线程更新状态和进度
我需要能够调用一个单独的线程。线程分析一个文件并从中提取统计信息 分析文件可能需要2分钟,分析期间,数据会打印到日志中 我想在前端有一个文本区,需要打印出分析(因为它是分析),我还想有一个进度条来指示进度。所有这些都是在单独的线程内确定的 我所做的是在UI类中创建一个方法,向文本区域添加一个字符串,并将该类的引用传递给启动的线程 我的主课Multithreading 如何在JavaFX中从单独的线程更新状态和进度,multithreading,textarea,javafx-2,output,Multithreading,Textarea,Javafx 2,Output,我需要能够调用一个单独的线程。线程分析一个文件并从中提取统计信息 分析文件可能需要2分钟,分析期间,数据会打印到日志中 我想在前端有一个文本区,需要打印出分析(因为它是分析),我还想有一个进度条来指示进度。所有这些都是在单独的线程内确定的 我所做的是在UI类中创建一个方法,向文本区域添加一个字符串,并将该类的引用传递给启动的线程 我的主课 package trymutilthread; import javafx.application.Application; import javafx.a
package trymutilthread;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class TryMutilThread extends Application {
TextArea ta;
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Button btn = new Button();
btn.setText("Start");
btn.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
startScheduledExecutorService();
}
});
ta = new TextArea();
VBox vBox = new VBox();
vBox.getChildren().addAll(btn, ta);
StackPane root = new StackPane();
root.getChildren().add(vBox);
Scene scene = new Scene(root, 300, 750);
primaryStage.setScene(scene);
primaryStage.show();
}
private void startScheduledExecutorService() {
final TryMutilThread classI = this;
Task<Void> task = new Task<Void>() {
@Override protected Void call() throws Exception {
try {
ta.appendText("Starting Thread\n");
new SomeProcess(classI).doTheLogic();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
};
Thread th = new Thread(task);
th.setDaemon(true);
th.start();
}
public void appendText(String string) {
ta.appendText(string);
}
}
然后我用谷歌搜索错误,似乎我需要将交互代码放在一个平台上。runlater()
我更改了类以执行要执行的线程
package trymutilthread;
import javafx.application.Platform;
public class SomeProcess {
TryMutilThread taClass = null;
public SomeProcess(TryMutilThread taClass) {
this.taClass = taClass;
}
public void doTheLogic() throws Exception {
taClass.appendText("Staring Thread");
for (int i = 0; i < 5000; i++) {
//remove this append line
//taClass.appendText(i + "\n");
//And replaced it with platform.runlater
Platform.runLater(new Runnable() {
@Override
public void run() {
taClass.appendText("AGREED" + "\n");
}
});
}
taClass.appendText("Ending Thread");
}
}
包trymutilthread;
导入javafx.application.Platform;
公共类进程{
TryMutilThread taClass=null;
公共进程(TryMutilThread taClass){
this.taClass=taClass;
}
public void doTheLogic()引发异常{
taClass.appendText(“起始线程”);
对于(int i=0;i<5000;i++){
//删除此附加行
//taClass.appendText(i+“\n”);
//并将其替换为platform.runlater
Platform.runLater(新的Runnable(){
@凌驾
公开募捐{
taClass.appendText(“同意”+“\n”);
}
});
}
taClass.appendText(“结束线程”);
}
}
它执行时没有任何错误,但现在似乎又回到了起点。。。UI被冻结,直到所有内容都添加到TextArea问题在于,FX应用程序线程中的请求太多;在Platform.runLater(…)调用之间没有实际的工作发生。这个问题可能会随着实际应用程序而不是本测试而消失,但是为了模拟实际的长时间运行工作,您可以在其中放置一个线程。sleep(…):
import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TextAreaBackgroundUpdateExample extends Application {
@Override
public void start(Stage primaryStage) {
final BorderPane root = new BorderPane();
final TextArea textArea = new TextArea();
final ProgressBar progress = new ProgressBar();
final Button startButton = new Button("Start");
final int maxCount = 5000 ;
startButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
for (int i = 1; i <= maxCount; i++) {
Thread.sleep(10);
final int count = i ;
Platform.runLater(new Runnable() {
@Override
public void run() {
textArea.appendText("Processed part " + count + " (of "+maxCount+")\n");
}
});
updateProgress(i, maxCount);
}
return null;
}
};
progress.progressProperty().bind(task.progressProperty());
Thread t = new Thread(task);
t.setDaemon(true);
t.start();
}
});
root.setCenter(textArea);
root.setTop(progress);
root.setBottom(startButton);
final Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
导入javafx.application.application;
导入javafx.application.Platform;
导入javafx.concurrent.Task;
导入javafx.event.ActionEvent;
导入javafx.event.EventHandler;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.control.ProgressBar;
导入javafx.scene.control.TextArea;
导入javafx.scene.layout.BorderPane;
导入javafx.stage.stage;
公共类TextAreaBackgroundUpdateExample扩展应用程序{
@凌驾
公共无效开始(阶段primaryStage){
最终边界窗格根=新边界窗格();
最终TextArea TextArea=新TextArea();
最终进度条进度=新进度条();
最终按钮开始按钮=新按钮(“开始”);
最终整数最大计数=5000;
setOnAction(新的EventHandler(){
@凌驾
公共无效句柄(ActionEvent事件){
任务=新任务(){
@凌驾
受保护的Void调用()引发异常{
对于(int i=1;i您的示例代码中没有后台线程;所有内容都在FX应用程序线程上运行。最好的方法是使用javafx.concurrent.Task。请参阅有很多示例的。James i更新了代码以使用任务。这似乎可行,但只要我有足够的代码添加,它似乎就实现了ning设置为fast,我得到了一个空指针。我搜索了错误,似乎应该在平台中添加代码。runLater(),但这再次冻结了UI。我用详细的注释修改了我的问题。
package trymutilthread;
import javafx.application.Platform;
public class SomeProcess {
TryMutilThread taClass = null;
public SomeProcess(TryMutilThread taClass) {
this.taClass = taClass;
}
public void doTheLogic() throws Exception {
taClass.appendText("Staring Thread");
for (int i = 0; i < 5000; i++) {
//remove this append line
//taClass.appendText(i + "\n");
//And replaced it with platform.runlater
Platform.runLater(new Runnable() {
@Override
public void run() {
taClass.appendText("AGREED" + "\n");
}
});
}
taClass.appendText("Ending Thread");
}
}
import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class TextAreaBackgroundUpdateExample extends Application {
@Override
public void start(Stage primaryStage) {
final BorderPane root = new BorderPane();
final TextArea textArea = new TextArea();
final ProgressBar progress = new ProgressBar();
final Button startButton = new Button("Start");
final int maxCount = 5000 ;
startButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent event) {
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
for (int i = 1; i <= maxCount; i++) {
Thread.sleep(10);
final int count = i ;
Platform.runLater(new Runnable() {
@Override
public void run() {
textArea.appendText("Processed part " + count + " (of "+maxCount+")\n");
}
});
updateProgress(i, maxCount);
}
return null;
}
};
progress.progressProperty().bind(task.progressProperty());
Thread t = new Thread(task);
t.setDaemon(true);
t.start();
}
});
root.setCenter(textArea);
root.setTop(progress);
root.setBottom(startButton);
final Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}