我需要能夠調用單獨的線程。線程分析一個文件並從中提取統計信息。如何從JavaFX中的單獨線程更新狀態和進度
文件分析最多可能需要2分鐘,在分析過程中,數據將打印到日誌中。
我想在前端有一個TextArea,需要打印出分析結果(因爲它分析),我也想有一個進度條來指示進度。所有這些都是在單獨的線程內部確定的。
我所做的是在UI類中創建一個方法,將字符串添加到文本區域並將此類的引用傳遞到啓動的線程。
我的主類
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);
}
}
是在線程
package trymutilthread;
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++) {
taClass.appendText(String.valueOf(i));
}
taClass.appendText("Ending Thread");
}
}
當我執行這一點,仍然只輸出文本將TextArea一旦線程已經結束執行現在的類。
我在下面的2個職位一看:
Java client/server thread null pointer exception when quickly communicating messages
我不能讓打印到日誌中的數據,直到該進程已經結束。
我更新了我的代碼以創建一個任務。 但現在我收到以下錯誤,當它執行
Executing com.javafx.main.Main from F:\DEV\Projects\TryMutilThread\dist\run404234128\TryMutilThread.jar using platform C:\Program Files\Java\jdk1.7.0_10/bin/java
java.lang.NullPointerException
at com.sun.javafx.sg.prism.NGTextHelper$TextAttributes.computeLinePadding(NGTextHelper.java:405)
at com.sun.javafx.sg.prism.NGTextHelper$TextAttributes.access$200(NGTextHelper.java:292)
at com.sun.javafx.sg.prism.NGTextHelper.buildTextLines(NGTextHelper.java:2357)
at com.sun.javafx.sg.prism.NGTextHelper.validateText(NGTextHelper.java:1847)
at com.sun.javafx.sg.prism.NGTextHelper.getCaretShape(NGTextHelper.java:1435)
at javafx.scene.text.Text.getDecorationShapes(Text.java:1150)
at javafx.scene.text.Text.impl_geomChanged(Text.java:757)
at javafx.scene.text.Text$1.invalidated(Text.java:214)
at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:127)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:161)
at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:67)
at javafx.scene.text.Text.setText(Text.java:188)
at com.sun.javafx.scene.control.skin.TextAreaSkin$17.invalidated(TextAreaSkin.java:610)
at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:359)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
at javafx.scene.control.TextInputControl$TextProperty.fireValueChangedEvent(TextInputControl.java:1034)
at javafx.scene.control.TextInputControl$TextProperty.markInvalid(TextInputControl.java:1038)
at javafx.scene.control.TextInputControl$TextProperty.invalidate(TextInputControl.java:978)
at javafx.scene.control.TextInputControl$TextProperty.access$200(TextInputControl.java:950)
at javafx.scene.control.TextInputControl$1.invalidated(TextInputControl.java:119)
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:155)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
at javafx.scene.control.TextArea$TextAreaContent.insert(TextArea.java:196)
at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:373)
at javafx.scene.control.TextInputControl.insertText(TextInputControl.java:308)
at javafx.scene.control.TextInputControl.appendText(TextInputControl.java:298)
at trymutilthread.TryMutilThread.appendText(TryMutilThread.java:80)
at trymutilthread.SomeProcess.doTheLogic(SomeProcess.java:26)
at trymutilthread.TryMutilThread$2.call(TryMutilThread.java:66)
at trymutilthread.TryMutilThread$2.call(TryMutilThread.java:62)
at javafx.concurrent.Task$TaskCallable.call(Task.java:1259)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
at java.util.concurrent.FutureTask.run(FutureTask.java:166)
at java.lang.Thread.run(Thread.java:722)
然後我google'd錯誤,看來我需要把交互代碼在Platform.runlater()。
Java client/server thread null pointer exception when quickly communicating messages
我改變了類來執行線程要
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");
}
}
它執行沒有任何錯誤,但現在它似乎是回到開始...的UI被凍結,直到所有被添加到TextArea中
你沒有背景線程在你的示例代碼中;一切都在FX應用程序線程上運行。做你想做的最好的方法是使用javafx.concurrent.Task。請參閱有很多示例的[Javadocs](http://docs.oracle.com/javafx/2/api/javafx/concurrent/Task.html)。 –
James I更新了代碼以使用任務。它似乎工作,但只要我有足夠的代碼來添加它似乎它發生得很快,我得到一個空指針。我google'd錯誤,似乎我應該在平臺中添加代碼。runLater()但是再次凍結UI。我用詳細的評論修改了我的問題。 – Chrispie