Launch JavaFX application from another class
Asked Answered
D

5

29

I need to start a javafx Application from another "container" class and call functions on the Application, but there doesn't seem to be any way of getting hold of a reference to the Application started using the Application.launch() method. Is this possible? Thanks

Ddt answered 16/9, 2014 at 16:17 Comment(0)
T
27

I had the same problem as this and got round it using this hack:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

import java.util.concurrent.CountDownLatch;

public class StartUpTest extends Application {
    public static final CountDownLatch latch = new CountDownLatch(1);
    public static StartUpTest startUpTest = null;

    public static StartUpTest waitForStartUpTest() {
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return startUpTest;
    }

    public static void setStartUpTest(StartUpTest startUpTest0) {
        startUpTest = startUpTest0;
        latch.countDown();
    }

    public StartUpTest() {
        setStartUpTest(this);
    }

    public void printSomething() {
        System.out.println("You called a method on the application");
    }

    @Override
    public void start(Stage stage) throws Exception {
        BorderPane pane = new BorderPane();
        Scene scene = new Scene(pane, 500, 500);
        stage.setScene(scene);

        Label label = new Label("Hello");
        pane.setCenter(label);

        stage.show();
    }

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

and then the class you are launching the application from:

public class StartUpStartUpTest {
    public static void main(String[] args) {
        new Thread() {
            @Override
            public void run() {
                javafx.application.Application.launch(StartUpTest.class);
            }
        }.start();
        StartUpTest startUpTest = StartUpTest.waitForStartUpTest();
        startUpTest.printSomething();
    }
}

Hope that helps you.

Torose answered 18/9, 2014 at 10:11 Comment(3)
Thanks that works well. I also found another way of doing it. If you start one Application then you can load stages into it from anywhere in your code base as long as you add the stage on the Application thread. You can use Platform.runLater() for that.Ddt
@Oli, can you post an example of this other way of doing it? I'm currently having the same problem.Stereochromy
How can you make printSomething() method execute after the application is exited ?Beeline
B
54

Suppose this is our JavaFX class:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;

public class OKButton extends Application {

    @Override
    public void start(Stage stage) {
        Button btn = new Button("OK");
        Scene scene = new Scene(btn, 200, 250);
        stage.setTitle("OK");
        stage.setScene(scene);
        stage.show();
    }
}

Then we may launch it from another class like this:

import javafx.application.Application;

public class Main {
    public static void main(String[] args) {
        Application.launch(OKButton.class, args);
    }
}
Bedstead answered 23/4, 2016 at 2:18 Comment(2)
This is a nice and simple way to "Launch JavaFX application from another class". However it does not allow " getting hold of a reference to the Application" as the OP wanted.Eventual
If you are like me, and are not running directly from main(), use new String[]{} instead of args. It creates an empty array as you would get usually.Selfdrive
T
27

I had the same problem as this and got round it using this hack:

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

import java.util.concurrent.CountDownLatch;

public class StartUpTest extends Application {
    public static final CountDownLatch latch = new CountDownLatch(1);
    public static StartUpTest startUpTest = null;

    public static StartUpTest waitForStartUpTest() {
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return startUpTest;
    }

    public static void setStartUpTest(StartUpTest startUpTest0) {
        startUpTest = startUpTest0;
        latch.countDown();
    }

    public StartUpTest() {
        setStartUpTest(this);
    }

    public void printSomething() {
        System.out.println("You called a method on the application");
    }

    @Override
    public void start(Stage stage) throws Exception {
        BorderPane pane = new BorderPane();
        Scene scene = new Scene(pane, 500, 500);
        stage.setScene(scene);

        Label label = new Label("Hello");
        pane.setCenter(label);

        stage.show();
    }

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

and then the class you are launching the application from:

public class StartUpStartUpTest {
    public static void main(String[] args) {
        new Thread() {
            @Override
            public void run() {
                javafx.application.Application.launch(StartUpTest.class);
            }
        }.start();
        StartUpTest startUpTest = StartUpTest.waitForStartUpTest();
        startUpTest.printSomething();
    }
}

Hope that helps you.

Torose answered 18/9, 2014 at 10:11 Comment(3)
Thanks that works well. I also found another way of doing it. If you start one Application then you can load stages into it from anywhere in your code base as long as you add the stage on the Application thread. You can use Platform.runLater() for that.Ddt
@Oli, can you post an example of this other way of doing it? I'm currently having the same problem.Stereochromy
How can you make printSomething() method execute after the application is exited ?Beeline
B
2

Launch JavaFX in other Class using Button:

    class Main extends Application{
      public void start(Stage s)throws Exception{
        event();
        s.show();
      }
      public void event(){
        btn.setOnAction(new EventHandler<ActionEvent>(){
          public void handle(ActionEvent ae){
            Stage s = new Stage();
            new SubClassName().start(s);
          }
        });
      }
      public static void main(String[] args) {
        launch(args);
      }
    }
    class SubClassName{
      public void start(Stage s){
        Pane pane = new Pane();
        Scene addFrame = new Scene(pane,280,450);
        s.setScene(addFrame);     
        s.show();
      }
    }
Bookshelf answered 18/11, 2018 at 11:24 Comment(0)
G
1

I'm not sure what you're trying to achieve, but note that you can e.g call from another class Application.launch to start the JavaFX Application thread and Platform.exit to stop it.

Garret answered 16/9, 2014 at 16:46 Comment(3)
Thanks, but Application.launch() is the problem. It constructs my Application for me but doesn't return a reference to it or allow me to pass any object to the Application's constructor! Is there another way of getting the constructed Application after launch has been called?Ddt
How do you call Application.launch() from another class? I get class [myclass] is not a subclass of javafx.application.Application errorBasuto
@JohnADurston The method is overloaded. Use this version: docs.oracle.com/javase/8/javafx/api/javafx/application/…Garret
B
1

The above ways of invoking other javafx class from another sometimes work. Struggling to find an ultimate way to do this brought me to the following walk around:

Suppose this is the javafx class that exteds Application we wish to show from a different class, then we should add the following lines

class ClassToCall extends Application{

  //Create a class field of type Shape preferably static...

  static Stage classStage = new Stage();

  @Override
  public void start(Stage primaryStage){

  // Assign the class's stage object to 
  // the method's local Stage object:

   classStage = primaryStage ;

  // Here comes some more code that creates a nice GUI.....
   // ......
  } 

}

And now from the other place in the project, in order to open the window that the above class creates do the following:

    // Suppose we want to do it with a button clicked:

    btn1.setOnAction(new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {

           //create an object of the class you wish to invoke its   
            //start() method:

            ClassToCall ctc = new ClassToCall();

          // Then call its start() method in the following way:

            ctc.start(ClassToCall.classStage);


       }// End handle(ActionEvent event)
     });// End anonymous class
Bike answered 26/9, 2016 at 7:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.