Application.launch() issue in javaFX 2.0 - java

In my code, I have used :
Application.launch(MyDesign.getClass(), null);
to run a UI of MyDesign from a seperate class.
When it calls launch(), it executes the constructor of MyDesign class. I have created a MyDesign object earlier and initialized its attributes. So I got a new object after calling launch(). I need to stop the calling its constructor when I call
Application.launch().
Your feed back is highly appreciated. Thanks.

Unfortunately you can't directly run already created Application through Application.launch().
You can use next stub application and launch it instead:
public class Runner extends Application {
#Override
public void start(Stage stage) throws Exception {
myDesignInstance.start(stage);
}
}

Related

How should I unit test the main method of a JavaFX program?

Right now, I'm considering incorporating 100% code coverage into my project. However, I'm having trouble unit testing the main entry point of my code:
public static void main(String[] args) {
launch(args);
}
This method is difficult to test because it launches an entirely new JavaFX program in the background. In addition to this behavior, a JavaFX program cannot be started more than once. Moreover, the documentation for javafx.application.Application explictly states that, "A JavaFX Application should not attempt to use JavaFX after the FX toolkit has terminated or from a ShutdownHook, that is, after the stop() method returns or System.exit(int) is called."
I am encountering this project because I'm also working with TestFX, a library that helps with clean testing for JavaFX. However, this library does not offer support for the testing of the main method, and as a result I have to write a workaround. There is a possibility of the developers of TestFX knowing about a possible workaround for this problem, for each and every unit tested method, a new instance of an Application is started. Perhaps there could be a way to completely shutdown and reset all variables of a JavaFX program.
To be fair, this method is not that significant to test, however it would be pleasant to have 100% code coverage. It would be entirely reasonable to not test this method as well. The full class can be found below:
package com.meti.app;
import javafx.application.Application;
import javafx.stage.Stage;
/**
* #author SirMathhman
* #version 0.0.0
* #since 4/5/2019
*/ //Main MUST remain public in order for JavaFX Application to start.
public class Main extends Application {
static InfinityImpl implementation = new Infinity();
static Main instance;
#Override
public void start(Stage primaryStage) {
instance = this;
implementation.start(primaryStage);
}
#Override
public void stop() {
implementation.stop();
instance = null;
}
public static void main(String[] args) {
launch(args);
}
}
The static variables above are irrelevant to the aforementioned question and are used for testing purposes in another class which ensures that the delegation works correctly. The application delegates most of the operations to a delegate class which makes the code easier to test.
Moreover, IntelliJ doesn't allow methods to be excluded during code testing.
If you have any other questions, please let me know. Thank you!
Some additional reading:
How to call launch() more than once in java
https://github.com/TestFX/TestFX/blob/master/subprojects/testfx-core/src/main/java/org/testfx/api/FxToolkit.java

JavaFX Application class - difference between default constructor and init method

I have written a little test application that looks like this:
import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;
public class Test extends Application {
public Test() {
System.out.println("first");
}
#Override
public void init() throws Exception {
System.out.println("second");
super.init();
}
#Override
public void start(Stage primaryStage) throws Exception {
System.out.println("third");
Platform.exit();
}
#Override
public void stop() throws Exception {
System.out.println("fourth");
super.stop();
}
public static void main(String[] args) {
launch(args);
}
}
The output is:
first
second
third
fourth
Now, I am asking myself where the difference is between using the default constructor or the init method for initialising some required things.
Thanks!
P.S.: This question is not duplicate with this one, because my issue does not handle the initialisation of variables. My question is JavaFX specific!
When the Application is launched, the following steps are executed during the launch process:
The instance of the Application subclass that should be launched is created. (Constructor is called)
The init() of that instance is called.
The start method of that instance is called.
See javadoc for Application
Since you exit the application after the start method is called, the stop method of the instance is called.
Note that there is no need to use super.init() and super.stop():
From the javadoc
The init and stop methods have concrete implementations that do nothing.
The differences of constructor, init and start are:
Constructor
If your application is not final the application class could be extended. Since the constructor of the extending class is not complete, it may be dangerous to pass a reference to the class to other classes in this state. Also the instance hasn't been initialized to a point where the getParameters method returns the parameters.
init
Initialisation should generally be done in this method. This method isn't run from the fx application thread, so some things cannot be done from this method, like creating a Stage.
start
Last step in the initialisation. Do things that require to be run from the application thread here. Be careful not to block this thread with long-runing operations however, since this freezes the GUI.
Application Class having init() method which you have override.
The Init method will call immediately after the Test class construction.
Init method is actually an internal method of Application Class. This method is actually initialize the whole FX application components internally.
Application class JavaDoc
it may construct other JavaFX objects in this method.

How to start new JavaFX (Application) thread?

I want to create a program in Java with a main window, that can open more subprograms in other windows.
I created a simple JavaFX program for the main window, and it works as expected, like so:
public class MainThread extends Application {
#Override
public void start(Stage primaryStage) {
// code goes here...
}
}
... and I created other Java classes the same way.
I tried to run them simply with new SubProgramThread();- as I would create a new instance of any object- but that hasn't worked for me- it doesn't run the start() method in the subprogram classes.
Is that the right way to create an Application instance?
Thanks.
I do this all the time. I have a menu of items. When a user clicks the item button I create the new window by calling start() on the FX class:
new TyAltSvr().start(new Stage());
Some people don't like calling start() but it hasn't caused me any problems.

Getting application instance in javafx

How can I get the application instance when using javafx?
Normally you launch an application this way:
public class LoginForm {
public static void main(String[] args) {
LoginApplication.launch(LoginApplication.class, args);
}
}
The method launch does not return an instance of application.
Is there a way I could get the instance?
I was just trying to find an easy, logical way to do exactly this. I haven't. It would be really nice if there was an Application.getApplicationFor(AppClass.class) that managed some singletons for you--but no.
If we restrict the problem space it's pretty easy to solve. If we make the class a singleton, then it's cake... A simplified singleton pattern should work fine:
class MyApp extends Application
{
public static MyApp me;
public MyApp()
{
me=this;
}
...
}
me can be null if it hasn't been instantiated by the system yet. It would be possible to protect against that with more code.
... implementing code...
Just implemented this--seems to work (barring any strange threading situations)
I have a slightly different situation, I'm wedging a javaFX screen into an existing swing GUI. It works fine, but I need to ensure that Application.launch is only called once. Adding this requirement, my final solution is thus:
(Sorry but the syntax has some groovy in it, should be easy for any Java user to translate)
class MyClass extends Application{
private static MyClass instance
public MyClass() {
instance=this
}
public synchronized static getInstance() {
if(!instance) {
Thread.start {
// Have to run in a thread because launch doesn't return
Application.launch(MyClass.class)
}
while(!instance)
Thread.sleep(100)
}
return instance
...
} // class
This manages blocking until Application.launch has completed instantiating the class, getting instances from other locations and ensuring that Application.launch gets called exactly once as long as getInstance has been called at least once.

JavaFX Not Able to Start From Non-FX Project In NetBeans Using Start

The problem I'm having is that when I create a new JavaFX project in NetBeans the main method is ignored, and somehow start() is somehow called and everything is just fine, but any time I try to call start I wind up with an exception. The class I used:
public final class JFXDriver extends Application {
public JFXDriver() {
Application.launch();
}
#Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("GUI.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
}
I've attempted to start it using the constructor, but it fails (Throws an Exception) for some reason saying that it is being called more than once, which should be impossible because I've constructed this class from a main method with only the new JFXDriver(); in it.
You are doing it wrong in the code. You should not call launch in your constructor. You should call it in your main and pass the name of the class that extends Application.
This causes the system to call init and then start and thus begins the lifecycle of your applicaton. For a more detailed explanation have a look here: http://codelatte.wordpress.com/2013/11/15/getting-started-with-javafx-hello-world-2/
Are you attempting a Swing and FX interop ?
Alright, I've found a solution to the problem. I added:
public static void start() {
Application.launch();
}
and took out the call to Application.launch() in the constructor. This approach worked. I guess that the JavaFX thread created its own instance of the class leading to the Application.launch() being called more than once. Interestingly, without the one application limit, I wonder if this would have led to a StackOverflowException due to the recursive nature of the call.

Categories