[英]Javafx Application with multiple windows for 2 different users . error Not on FX application thread;
我正在構建一個 Java 獨立應用程序,兩個不同的用戶使用兩個不同的 GUI。 我想要兩個不同的線程,每個線程必須管理一個 GUI。 我有錯誤
線程“Thread-4”java.lang.IllegalStateException 中的異常:不在 FX 應用程序線程上; currentThread = Thread-4
我該如何解決?
package kapta.classes;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;
import kapta.classes.Utils.ThreadLocalSession;
import java.io.IOException;
public class MainApp extends Application {
@Override
public void start(Stage stage) throws IOException {
System.out.println("here main");
FXMLLoader fxmlLoader = new FXMLLoader(MainApp.class.getResource("Login.fxml"));
Scene scene = new Scene(fxmlLoader.load());
stage.setTitle("Mate");
stage.setScene(scene);
//stage.setFullScreen(true);
stage.show();
ThreadLocalSession firstUser = new ThreadLocalSession();
new Thread(firstUser).start();
}
public static void main(String[] args) {
launch();
}
}
在 class ThreadLocalSession ==>
package kapta.classes.Utils;
public class ThreadLocalSession implements Runnable
{
private static ThreadLocal<Session> userSession;
private String username;
public ThreadLocalSession(){}
public ThreadLocalSession(String username){
this.username = username;
this.userSession = new ThreadLocal<>();
}
public void setUsername(String username) {
this.username = username;
}
public static void setUserSession(ThreadLocal<Session> userSession) {
ThreadLocalSession.userSession = userSession;
}
public String getUsername() {
return username;
}
public static ThreadLocal<Session> getUserSession() {
return userSession;
}
@Override
public void run() {
System.out.println("1");
try {
Platform.runLater(display());
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
private Runnable display() throws IOException, InterruptedException {
Thread.sleep(1000);
System.out.println("trd");
Stage stage = new Stage();
FXMLLoader fxmlLoader = new FXMLLoader(MainApp.class.getResource("Login.fxml"));
Scene scene = new Scene(fxmlLoader.load());
stage.setTitle("New");
stage.setScene(scene);
stage.showAndWait();
return null;
}
您應該將 Runnable 傳遞給 runLater 方法,發生的情況是您將 null 從顯示方法作為 Runnable 返回到 runLater,而實際的新 window 創建仍在調用顯示方法的線程中,這會導致異常。 嘗試將 Runnable 傳遞給 runLater:
@Override
public void run() {
System.out.println("1");
Platform.runLater(()->{
System.out.println("trd");
Stage stage = new Stage();
FXMLLoader fxmlLoader = new FXMLLoader(MainApp.class.getResource("Login.fxml"));
Scene scene = new Scene(fxmlLoader.load());
stage.setTitle("New");
stage.setScene(scene);
stage.showAndWait();
});
}
// or Platform.runLater(()->display())
/* or in the old fashion:
Platform.runLater(new Runnable{
@override
public void run(){ display(); }
});
*/
我認為您誤解了如何將 Runnable object 傳遞給 Platform.runLater 之類的方法。
您的display()
方法根本沒有創建 Runnable。 事實上,它總是返回 null,因此。 您根本沒有將 Runnable 傳遞給 Platform.runLater。
相反, display()
會立即執行所有 JavaFX 代碼。 換句話說,這一行:
Platform.runLater(display());
完全等同於:
Runnable task = display();
Platform.runLater(task);
問你可以看到,在調用 Platform.runLater之前display()
已經完全執行。 所以它實際上根本沒有在以后運行:這是您看到的異常的原因:您在ThreadLocalSession.run()
本身中運行代碼,而不是在 JavaFX 平台線程中。
此外,當前形式的display()
方法不適合在 JavaFX 平台線程中運行,因為在該線程中不允許調用 Thread.sleep。 編譯器不會檢測到它,運行時也不能阻止你這樣做,但這樣做會導致所有事件處理在睡眠期間暫停。 在此期間,不會繪制任何節點,不會識別用戶輸入,也不會出現 windows。
您要做的是從您的run()
方法調用 Thread.sleep,然后返回一個包含所有剩余代碼的 Runnable:
private Runnable display() throws IOException, InterruptedException {
// This method is called from ThreadLocalSession.run(), so
// we are not in the JavaFX platform thread.
Thread.sleep(1000);
Runnable displayer = new Runnable() {
@Override
public void run() {
System.out.println("trd");
Stage stage = new Stage();
FXMLLoader fxmlLoader = new FXMLLoader(MainApp.class.getResource("Login.fxml"));
try {
Scene scene = new Scene(fxmlLoader.load());
stage.setTitle("New");
stage.setScene(scene);
stage.showAndWait();
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
};
return displayer;
}
(你也可以寫一個 lambda 來表示一個 Runnable,但為了清楚起見,我選擇使用顯式語法。)
Runnable 的 run() 方法不允許拋出 IOException 這樣的已檢查異常,這就是為什么 IOException 需要在該方法內部捕獲的原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.