JavaFX launch another application

2020-01-23 13:14发布

I've been smashing my head with JavaFx...

This works for when there's no instances of an application running:

public class Runner {

    public static void main(String[] args) {
        anotherApp app = new anotherApp();
        new Thread(app).start();
    }
 }

public class anotherApp extends Application implements Runnable {

    @Override
    public void start(Stage stage) {
    }

    @Override
    public void run(){
        launch();
    }
}

But if I do new Thread(app).start() within another application I get an exception stating that I can't do two launches.

Also my method is called by an observer on the other application like this:

@Override
public void update(Observable o, Object arg) {
    // new anotherApp().start(new Stage());
            /* Not on FX application thread; exception */

    // new Thread(new anotherApp()).start();
            /* java.lang.IllegalStateException: Application launch must not be called more than once */
}

It's within a JavaFX class such as this:

public class Runner extends Applications implements Observer {

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage stage){
    //...code...//
    }
    //...methods..//
    //...methods..//

    @Override
    public void update(Observable o, Object arg) {
    //the code posted above//
    }
}

I tried using ObjectProperties with listeners but it didn't work. I need to get this new stage running from within the update method from java.util.observer in some way.

Any suggestions are welcomed. Thanks.

3条回答
Root(大扎)
2楼-- · 2020-01-23 13:21

Wanted to provide a second answer because of one caveat of using
Application.start(Stage stage).

The start method is called after the init method has returned

If your JavaFX application has Override Application.init() then that code is never executed. Neither is any code you have in the second application main method.

Another way to start a second JavaFX application is by using the ProcessBuilder API to start a new process.

    final String javaHome = System.getProperty("java.home");
    final String javaBin = javaHome + File.separator + "bin" + File.separator + "java";
    final String classpath = System.getProperty("java.class.path");
    final Class<TestApplication2> klass = TestApplication2.class;
    final String className = klass.getCanonicalName();
    final ProcessBuilder builder = new ProcessBuilder(javaBin, "-cp", classpath, className);

    final Button button = new Button("Launch");
    button.setOnAction(event -> {

        try {
            Process process = builder.start();
        } catch (IOException e) {
            e.printStackTrace();
        }

    });
查看更多
\"骚年 ilove
3楼-- · 2020-01-23 13:31

I did a constructor of another JFX class in Main class AnotherClass ac = new AnotherClass(); and then called the method ac.start(new Stage);. it worked me fine. U can put it either in main() or in another method. It does probably the same thing the launch(args) method does

查看更多
太酷不给撩
4楼-- · 2020-01-23 13:42

Application is not just a window -- it's a Process. Thus only one Application#launch() is allowed per VM.

If you want to have a new window -- create a Stage.

If you really want to reuse anotherApp class, just wrap it in Platform.runLater()

@Override
public void update(Observable o, Object arg) {
    Platform.runLater(new Runnable() {
       public void run() {             
           new anotherApp().start(new Stage());
       }
    });
}
查看更多
登录 后发表回答