首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将JavaFX8GUI与其余代码分离

将JavaFX8GUI与其余代码分离
EN

Stack Overflow用户
提问于 2015-08-11 16:51:38
回答 3查看 770关注 0票数 2

在阅读javafx 8教程时,这似乎是主要的工作流程:

代码语言:javascript
复制
public class Test extends Application{
    public static void main(String[] args){
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        FXMLLoader fxmlLoader = new FXMLLoader(TestFXController.class.getResource("test.fxml"));
        Parent root;
        try {
            root = fxmlLoader.load();
            Scene scene = new Scene(root, 1200, 800);
            primaryStage.setScene(scene);
            primaryStage.show();
            TestFXController controller = fxmlLoader.getController();
            controller.plotSomething();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

假设我有一个我想运行的算法。启动上述应用程序后,我可能会得到一个包含"run algorithm“按钮的接口。按下按钮后,动作处理程序将调用该算法。然后我有:启动java应用程序->构建界面->按下按钮解决算法->显示解决方案。将图形内容与算法分离开来的只是一个按钮。实际上,图形界面“驱动”应用程序,因为它负责启动算法。然而,我更喜欢的是这样的:

代码语言:javascript
复制
public class Test2{
    public void main(String[] args){
        Algorithm alg=new Algorithm();
        alg.solve();
        GUI gui =new GUI(); //Spawns a Javafx 8 Graphical User Interface
        gui.displaySolution(alg.getSolution());
    }
}

对我来说,这看起来更干净?但是,我不知道如何使用javafx 8来完成这个任务,或者这是否是可能的?任何例子或参考资料都将受到高度赞赏。我应该在GUI类中添加什么,以使它启动javafx 8接口?Test2中的示例还提供了使用干净的观察者设计模式的可能性,如下所示:

代码语言:javascript
复制
public class Test3{
    public void main(String[] args){
        Algorithm alg=new Algorithm();
        alg.addListener(new GUI()); //Add a Javafx 8 GUI as a listener.
        alg.addListener(new TextualLogger());
        alg.solve();
    }
}

注意,在Test2和Test3类中,GUI不再驱动应用程序。

为了澄清,我的主要问题是:如果我要在Test2中运行代码,那么GUI类的实现应该是什么?就像这样:

代码语言:javascript
复制
public class GUI extends Application{

  public GUI(){
    //What should I put here? Perhaps launch(new String[]); ?
  }

  @Override
  public void start(Stage primaryStage) throws Exception {
    FXMLLoader fxmlLoader = new FXMLLoader(TestFXController.class.getResource("test.fxml"));
    Parent root;
    try {
    root = fxmlLoader.load();
    Scene scene = new Scene(root, 1200, 800);
    primaryStage.setScene(scene);
    primaryStage.show();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public void displaySolution(Solution sol){
    ...
  }

}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-08-11 18:08:55

在JavaFX应用程序中,您应该将start(...)方法从本质上看作是“常规”main(...)应用程序中的main(...)方法。(实际上,在Java8中,JavaFX应用程序根本不需要main(...)方法。)引入这种启动JavaFX应用程序的机制是为了迫使程序员尽可能地在正确的线程上初始化UI (与Swing相比,Swing中有大量错误启动GUI的代码)。为了方便起见,start(...)方法通过了初始阶段,但是如果您喜欢使用不同的方法,则不需要使用它。

所以你就可以

代码语言:javascript
复制
public class Test2 extends Application {

    @Override
    public void start(Stage primaryStage) {
        Algorithm alg = new Algorithm();
        alg.solve();
        GUI gui = new GUI();
        gui.displaySolution(alg.getSolution());
    }

    // included for the benefit of IDEs that do not support
    // launching an Application without a main method:
    public static void main(String[] args) { launch(args); }
}

现在,GUI不是Application子类(这很有意义,因为它代表的是GUI,而不是应用程序):

代码语言:javascript
复制
public class GUI {

  public GUI(){

    FXMLLoader fxmlLoader = new FXMLLoader(TestFXController.class.getResource("test.fxml"));
    Parent root;
    try {
        root = fxmlLoader.load();
        Scene scene = new Scene(root, 1200, 800);
        Stage stage = new Stage();
        stage.setScene(scene);
        stage.show();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public void displaySolution(Solution sol){
    ...
  }

}

这里需要记住的一点是,start(...)是在上执行的。因此,一旦显示了UI,任何需要执行的长时间运行的进程都应该在后台线程上执行。在您所描述的用例中,所有的繁重工作都是在显示UI之前完成的,所以这不是一个问题,但是如果您想要扩展这个模式,您可能需要考虑这一点。

票数 3
EN

Stack Overflow用户

发布于 2015-08-11 16:58:18

我不确定我是否完全遵循了你想要做的事情--你是想打开第二个JavaFX窗口吗?

像这样的东西有用吗?

代码语言:javascript
复制
Scene resultScene = algorithm.getSolution();
Stage resultStage = new Stage();
resultStage.setScene(resultScene);
resultStage.addEventHandler() or addEventFilter()
resultStage.show();

这个阶段可以是它自己的窗口,也可以是primaryStage的子窗口,所以如果关闭父窗口,它也会关闭。

票数 0
EN

Stack Overflow用户

发布于 2016-06-11 06:45:12

如果您真的想从一个已经运行的窗口中打开第二个JavaFX窗口。你可以去看看。

Launch JavaFX application from another class

它会解决你的问题。

下面是如何运行新的JavaFx应用程序的代码

代码语言:javascript
复制
        Platform.runLater(new Runnable(){
            @Override
            public void run(){
                new MainApp().start(new Stage()); // MainApp is the class name of your second Application
            }
        });

使类扩展应用程序并实现Runnable,并在该类中添加下面提到的代码

代码语言:javascript
复制
@Override
public void run(){
    launch();
}

启动()方法将从run()方法调用。不要在第二个类中使用Main()方法,否则会抛出异常。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31947591

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档