JavaFX从另一个应用程序启动Application standalone OR

时间:2014-09-11 14:02:51

标签: java javafx

在场景之后:

JavaFxMainApp JavaFXUpdaterApp

两者都是带有GUI和void main()方法的JavaFX应用程序。

  1. Updater必须能够通过访问来启动JavaFXMainApp JavaFxMainApp.jar只知道主类 - >它只能!呼叫 main()中。

  2. JavaFxMainApp也必须能够通过启动自行运行     main()中。

  3. 我无法启动多个VMS,这两个应用程序无法通信。

    问题是:

    Application.launch()每个JVM只能执行一次。

    启动应用的标准javaFx方式:

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

    这里不可能满足要求1)。因为两个main()方法都调用launch()。

    我找到的第二种方法是:

    Updater + MainApp
     public static void main(String[] args) {
            Application app2 = JavaFxMainApp.class.newInstance(); 
            Stage anotherStage = new Stage();
            app2.start(anotherStage);
    }
    

    首先,我失去了传递args的可能性,但是我可以忍受它,因为它们不会被使用。 这里的主要问题是,如果JVM已经运行了JavaFx线程,则此代码仅起作用,因此它要求在之前的某个时刻在JVM中调用launch()。情况并非如此,因为两个调用都不再是launch()。

    混合方法:

    Updater calls launch(), MainApp takes the second approach
    

    要求2)无法实现,现在无法在没有启动器更新程序的情况下启动MainApp。

    我有另外一个想法肮脏"尝试launch()catch() - >尝试在两个应用程序中使用第二种方法(),但这会使两个应用程序结合并使设置不那么灵活。

    有没有办法在不必覆盖JavaFxs的情况下实现这一目标。 LauncherImpl或Application类是否符合这些需求?

2 个答案:

答案 0 :(得分:3)

你能做这样的事吗:

public class MainApp extends Application {

    private Parent uiContent ;

    public static final double DEFAULT_WIDTH = 800 ;
    public static final double DEFAULT_HEIGHT = 600 ;

    public Parent getContent() {
        if (uiContent == null) {
            uiContent = initializeUI();
        }
        return uiContent ;
    }

    public Scene createScene() {
        return new Scene(getContent(), DEFAULT_WIDTH, DEFAULT_HEIGHT);
    }

    public void initializeAndShowStage(Stage stage) {
        stage.setScene(createScene());
        stage.show();
    }

    private Parent initializeUI() {
        // probably wise to check we are on the FX Application thread here...
        Pane root = ... ;
        // build ui....
        return root ;
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        initializeAndShowStage(primaryStage);
    }

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

public class UpdaterApp extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        // whatever you need to launch the updater app here...

    }

    // invoke from the FX Application Thread to "start" main app:
    private void showMainApp(Stage stage) {
        MainApp app = new MainApp();
        app.initializeAndShowStage(stage);
    }

    private void showMainApp() {
        showMainApp(new Stage());
    }

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

这将是最受欢迎的方法。如果您有强制要求main的要求,那么您可以尝试这样的事情:

public class MainApp extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        // .... build UI etc
    }

    public static void main(String[] args) throws Exception {
        if (Platform.isFXApplicationThread()) {
            Stage someStage = new Stage();
            MainApp app = new MainApp();
            app.start(stage);
        } else {
            launch(args);
        }
    }
}

然后您的更新程序应用程序只能从FX应用程序主题调用MainApp().main(new String[0]));

这感觉有点像黑客。

答案 1 :(得分:3)

您希望您的MainApp自己启动,并且您还希望UpdateApp在需要时启动MainApp,然后您可以按照我的步骤操作。我试过了,这个模型正在运作。

这是起点。您需要调用此类来开始您的应用程序

public class StartAnApp {
    public static void main(String[] args){
        new Thread(new MainApp()).start(); // this will call your MainApp 
    }
}

这是第一个将开始的应用程序。至于启动JavaFX应用程序,您需要有一个main()方法。因此,请确保在此课程中提供主要方法。

public class MainApp extends Application implements Runnable{
    public MainApp(){}  // constructor

    @Override
    public void start(Stage stage){
        Text text = new Text("MainApp");
        Button startUpdate = new Button("Start Update");

        // When this button is pressed. It will launch UpdateApp Application
        startUpdate.setOnAction( e -> {
            Platform.runLater(new Runnable(){
                @Override
                public void run(){
                    new UpdateApp().start(new Stage());
                }
            });
        });

        Group root = new Group(text);
        Scene scene = new Scene(root,300,400);
        stage.setScene(scene);
        stage.setX(0);
        stage.setY(0);
        stage.show();
    }

    // This method will be used when you first start an Application for
    // which main method is required
    public static void main(String[] args){
        launch(args);
    }

    // This will be used when you call this Application from another JavaFX application
    // if you have closed this application before
    @Override
    public void run(){
        launch();
    }
}

这是您的UpdateApp。此方法没有main()方法。

public class UpdateApp extends Application implements Runnable{
    public UpdateApp(){}  // constructor

    @Override
    public void start(Stage stage){
        Text text = new Text("UpdateApp");
        Button startAnother = new Button("Start Another");

        // When this button is pressed. It will launch MainApp Application or you can add any other JavaApplication
        startAnother.setOnAction( e -> {
            Platform.runLater(new Runnable(){
                @Override
                public void run(){
                    new MainApp().start(new Stage());
                }
            });
        });

        Group root = new Group(text);
        Scene scene = new Scene(root,300,400);
        stage.setScene(scene);
        stage.setX(350);
        stage.setY(0);
        stage.show();
    }

    // This will be used when you call this Application from another JavaFX application
    @Override
    public void run(){
        launch();
    }
}