我有一个MainWindowFx类,如下所示。它基本上创建了一个简单的JavaFX
GUI。
package drawappfx;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.Button;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.VBox;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.control.TextAreaBuilder;
/**
*
* @author Hieu
*/
public class MainWindowFX extends Application{
public static final int DEFAULT_WIDTH = 600;
public static final int DEFAULT_HEIGHT = 600;
private int width;
private int height;
private Scene scene;
private TextArea messageView;
private Button quitButton;
private BorderPane layout;
private Stage primaryStage;
@Override
public void start(Stage primaryStage) {
System.out.println("Started building GUI....");
this.buildGUI();
System.out.println("Finished building GUI");
this.primaryStage = primaryStage;
primaryStage.setTitle("Hello World!");
primaryStage.setScene(this.scene);
primaryStage.show();
System.out.println("Where the hell are you?");
}
public Scene getScene() {
return this.scene;
}
public BorderPane getBorderPane() {
return this.layout;
}
public Stage getPrimaryStage() {
return this.primaryStage;
}
public void buildGUI() {
System.out.println("Before layout");
this.layout = new BorderPane();
System.out.println("Before vbox");
this.layout.setBottom(this.addVBox());
System.out.println("before new scene");
this.scene = new Scene(this.layout, DEFAULT_WIDTH, DEFAULT_HEIGHT);
System.out.println("after new scene");
}
public VBox addVBox() {
VBox vbox = new VBox();
vbox.setPadding(new Insets(15, 12, 15, 12));
// message box
this.messageView = TextAreaBuilder.create()
.prefRowCount(5)
.editable(false)
.build();
// quit button
this.quitButton = new Button("Quit");
this.quitButton.setPrefSize(100, 20);
System.out.println("think of a good message?");
vbox.getChildren().addAll(this.messageView, this.quitButton);
System.out.println("before returning vbox");
return vbox;
}
public void postMessage(final String s) {
this.messageView.appendText(s);
}
}
现在我想在另一个类中使用此对象的实例:
package drawappfx;
import java.io.InputStreamReader;
import java.io.Reader;
import javafx.scene.layout.BorderPane;
public class DrawAppFx
{
public static void main(String[] args)
{
final MainWindowFX main = new MainWindowFX();
BorderPane layout = main.getBorderPane();
Reader reader = new InputStreamReader(System.in);
Parser parser = new Parser(reader,layout,main);
main.start(main.getPrimaryStage());
parser.parse();
}
}
但是当我运行这个时,我遇到了这个错误:
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at com.javafx.main.Main.launchApp(Main.java:658)
at com.javafx.main.Main.main(Main.java:805)
Caused by: java.lang.IllegalStateException: Not on FX application thread; currentThread = main
at com.sun.javafx.tk.Toolkit.checkFxUserThread(Toolkit.java:237)
at com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:397)
at javafx.scene.Scene.<init>(Scene.java:287)
at javafx.scene.Scene.<init>(Scene.java:226)
at drawappfx.MainWindowFX.buildGUI(MainWindowFX.java:74)
at drawappfx.MainWindowFX.start(MainWindowFX.java:47)
at drawappfx.DrawAppFx.main(DrawAppFx.java:39)
... 6 more
Java Result: 1
我已经对此进行了一些搜索并猜测它与线程有关......但我仍然不知道。有什么建议吗?
答案 0 :(得分:6)
我已经多次遇到过这个问题,并且有一种相当简单的方法可以解决它。
首先让我向您介绍Mediator pattern,基本上您要创建一个与所有 GUI 类有关系的类
(即不同的GUI类没有彼此自己的实例,而是所有这些实例都与Mediator具有相同的引用。)
现在对你的问题来说这是一个偏见。
为了更改窗口,您需要传递应放置新窗口的Stage
,因此您的代码只需稍作更改:
现在我不经常这样做,但在你的情况下,我会做一个例外,下面的代码包含一个类,你可以“复制粘贴”到你的程序中并使用它来修复问题后我会解释代码正是我所做的:
<强>中保强>
public class Mediator extends Application {
private DrawAppFx daf;
private MainWindowFX mainWindow;
private Stage primaryStage;
public Mediator(){
daf = new DrawAppFx(this);
mainWindow = new MainWindowFx(this);
}
public static void main(String[] args){
launch(args);
}
@Override
public void start(Stage stage) throws Exception {
primaryStage = stage;
mainWindow.start(primaryStage);
}
public void changeToDaf(){
daf.start(primaryStage);
}
}
现在DrawAppFx
和MainWindowFx
中的每一个都必须有一个传递Mediator对象的构造函数,因此与调解器具有“ Has-a ”关系
这背后的原因是中介模式现在处于控制状态,如果您创建更多窗口,则很容易实现,只需将它们添加到中介并添加中介可以更改到该窗口的方法。