当前位置: 首页 > 知识库问答 >
问题:

使用另一个类中的JavaFx应用程序实例

宿镜
2023-03-14

我有一个如下所示的MainWindowFx类。它基本上创建了一个简单的JavaFXGUI。

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

我对此做了一些搜索,并猜测它与线程有关。。。但我还是不知道。有什么建议吗?

共有1个答案

薄兴昌
2023-03-14

我已经有过好几次这样的问题,有一个相当简单的方法来解决它。

首先,让我向您介绍Mediator模式,基本上您想要创建一个与所有GUI类都有关系的类

(也就是说,不同的GUI类之间没有各自的实例,而所有GUI类都对中介具有相同的引用)。

这是你问题的旁白。

要更改窗口,您需要通过阶段,新窗口应放在该阶段,因此您的代码只需稍作更改:

现在我不经常这样做,但在你的情况下,我会破例以下代码由一个类,你可以"复制粘贴"到你的程序,并使用,将解决问题后的代码我会解释我到底做了什么:

调解人

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);
    }
}

现在,每个DrawAppFxMain WindowFx都必须具有传递Mediator对象的构造函数,因此与中介具有Has-a关系

这背后的原因是中介模式现在处于控制之中,如果您创建更多的窗口,那么很容易实现,只需将它们添加到中介中,并添加一个中介可以更改为该窗口的方法即可。

 类似资料:
  • 问题内容: 我需要从另一个“容器”类启动一个Javafx应用程序,并在该应用程序上调用函数,但是似乎没有任何方法可以使用Application.launch()方法来获取对该应用程序的引用。这可能吗?谢谢 问题答案: 我遇到了同样的问题,并使用此hack解决了这个问题: 然后是您要从中启动应用程序的类: 希望对您有帮助。

  • 问题内容: 我确信你们中有人注意到,如果您有Acrobat Reader(或其他PDF阅读器),并在Firefox中打开一个PDF,您会看到它嵌入在您的标签中。有什么方法可以将应用程序嵌入JFrame中? 问题答案: 这是一个相当棘手的问题。通常,诸如Adobe Reader之类的本机应用程序不提供可以嵌入到swing应用程序中的组件。但是在Windows中,有COM / OLE方法可以将应用程序

  • 我有两个应用程序:同事和服务,每个都有自己的模型 在coworkers models.py中,我可以“从services.models导入服务”。 当我尝试在services models.py中“from coworkers.models import Status”时,会收到以下错误消息: 回溯(最近一次调用):文件“/Users/lucas/Documents/projetos/cwk-ma

  • 我正在我的UI线程中调用一个方法。在这个方法中创建了一个新线程。我需要UI线程等待这个新线程完成,因为我需要这个线程的结果来继续UI线程中的方法。但我不想让UI在等待时冻结。有没有办法让UI线程在不忙的情况下等待?。

  • 我正在开发两个应用程序。让第一个应用程序是APP1,第二个应用程序为APP2。现在在APP1中,我不提供任何用户权限,如INTERNET权限,但它将发送任何http url,如http://www.google.com我的第二个APP2将包含INTERNET等用户权限。Http请求将从APP1发送到APP2,APP2将响应该请求,然后将结果发送回APP1。最后APP1包含一个Web视图以显示结果。

  • 问题内容: 我有两个单独的节点应用程序。我希望其中一个能够在代码中的某个时刻启动另一个。我将如何去做? 问题答案: 使用。它与相似,但是用于创建V8的全新实例。因此,它专门用于运行Node的新实例。如果您只是执行命令,请使用或。 请注意,默认情况下使用时,流与父级关联。这意味着所有输出和错误都将在父进程中显示。如果您不希望与父级共享流,则可以在选项中定义属性: 然后,您可以将流程与主流程的流分开处