0

I am writing a java class extending the application class of javafx and am trying to pass an object into the constructor like so:

public class SceneWindow extends Application{
    
    private int x;
    private int y;
    private int textX;
    private int textY;
    private static ImagePattern img;
    public String title;
    private ArrayList<EventHandler<MouseEvent>> events = new ArrayList<EventHandler<MouseEvent>>(); 
    private Text mainDialogue = new Text(0, 0, "test");
    private int eventIndex = 0;
    
    
    public SceneWindow(SceneManager sm){ 
        x = sm.getWindowX();
        y = sm.getWindowY();
        
        textX = sm.getTextX();
        textY = sm.getTextY();
        
        img = sm.getBackground();
        title = sm.getTitle();
        events = sm.getEvents();
        mainDialogue.setText(sm.getText());
        
    }

I am creating an instance of SceneWindow like this:

SceneWindow sw = new SceneWindow(sm);

with sm being a SceneManager object.

However this is not working. I have read elsewhere that this is because you are unable to have a non-zero parameter in a javafx constructor.

This is the error message I am getting:

Exception in Application constructor
Exception in thread "main" java.lang.RuntimeException: Unable to construct Application instance: class application.SceneWindow
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:891)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NoSuchMethodException: application.SceneWindow.<init>()
    at java.base/java.lang.Class.getConstructor0(Class.java:3585)
    at java.base/java.lang.Class.getConstructor(Class.java:2271)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$8(LauncherImpl.java:802)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
    ... 1 more

How can I get around this?

jewelsea
  • 150,031
  • 14
  • 366
  • 406
ErgonomicGrip
  • 15
  • 1
  • 2
  • 1
    Yes, looks like it needs a non-arg constrcutor, so make one and then some setters, and then some other init method? – Scary Wombat Jan 14 '22 at 00:30
  • 1
    You don’t ever instantiate the `Application` class anyway; how would you use this constructor? Why not just create the `SceneManager` instance in the `start()` method? – James_D Jan 14 '22 at 00:53
  • @James_D is the ```Application``` class not instantiated when i run ```SceneWindow sw = new SceneWindow(sm);```, as ```SceneWindow``` extends ```Application```? After I instantiate a SceneManager instance I interact with it before passing it into SceneWindow. If i instantiate it in start(), it will be empty. – ErgonomicGrip Jan 14 '22 at 00:59
  • 1
    @ErgonomicGrip Well it would be, but you should never do that. The `Application` class is instantiated for you when you launch the application, and you should only have one `Application` instance. – James_D Jan 14 '22 at 01:01
  • @James_D I am running ```SceneWindow sw = new SceneWindow(sm);``` in an external class. I am only creating one instance of SceneWindow. Unless I am misunderstanding which is very possible. – ErgonomicGrip Jan 14 '22 at 01:06
  • @ErgonomicGrip The `Application` class is the entry point for the entire application. It is necessarily the first class that is instantiated in a JavaFX application, since it manages the lifecycle of the entire application. You can override the `init()` method and do any initialization, such as creating your `SceneManager` instance and configuring it. – James_D Jan 14 '22 at 01:09
  • 1
    As I said in a previous comment, an instance of your `Application` class is created when you call `Application.launch(…)`. So if you instantiate it yourself, you have at least two instances. It makes no sense to have two instances of a class whose entire purpose is to manage the application lifecycle. – James_D Jan 14 '22 at 01:10
  • [Passing reference to javafx. Application](https://stackoverflow.com/questions/53003746/passing-reference-to-javafx-application-application) may help – c0der Jan 14 '22 at 12:50

1 Answers1

4

I am writing a java class extending the application class of javafx and am trying to pass an object into the constructor

Do not try to pass an object into the constructor of a JavaFX Application.

Read the JavaFX Application javadoc:

The Application subclass must be declared public and must have a public no-argument constructor.

Additionally, study the application lifecycle information in the linked javadoc.

You should only have a single application instance within the VM and that will be created by the application launch sequence which invokes the no-args constructor.

Therefore creating an additional constructor for the application which has arguments is pointless at best as it should never be called.


Why you shouldn't manually create a new application instance

If your parameterized constructor were manually called via new, yes it would create a new application instance. But then you would have two instances in the VM, one created manually by you, and one automatically created by the launcher, and they would have different states of initialization and one would be managed by the JavaFX lifecycle and one (the one you manually created) would not, which would just be an unnecessarily confusing and error-prone situation to create => you should never manually create a JavaFX Application instance.

Command line args

Note: You can provide a static main method that has a standard String[] args argument list, and those parameters will be available to the application instance via getParameters(), so it is possible to pass arguments to the application instance, but those arguments are a completely different thing then what you are trying to do as they are just command line string arguments, not arbitrary Java object references. The arguments are passed as parameters to the application class instance via the launch(appClass, args) method.

jewelsea
  • 150,031
  • 14
  • 366
  • 406