Question

I used the Oracle FXML Sample for my Java project. The thing is that I have 2 FXML-files (load.fxml, main.fxml). I first load the load.fxml and then want to press a button triggering a method (handleLoadButton()) to load the main.fxml. This doesn't work though. I get an error "JavaFX Application Thread". So maybe I'm an idiot, but I currently am frustated a bit, because I cannot find any solution for this. How would I load the main.fxml?

My code sofar:

import java.io.IOException;

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    private Stage myStage;

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

    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("load.fxml"));

        stage.setTitle("FXML Welcome");
        stage.setScene(new Scene(root, 300, 275));
        stage.show();

        myStage = stage;
    }

    @FXML
    private void handleLoadButton() throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));

        myStage.setTitle("FXML Main");
        myStage.setScene(new Scene(root, 300, 275));
        myStage.show();
    }
}

The error I get:

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1449)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:69)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:28)
    at javafx.event.Event.fireEvent(Event.java:171)
    at javafx.scene.Node.fireEvent(Node.java:6867)
    at javafx.scene.control.Button.fire(Button.java:179)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:193)
    at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:336)
    at com.sun.javafx.scene.control.skin.SkinBase$4.handle(SkinBase.java:329)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:64)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:217)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:170)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:38)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:37)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:35)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:92)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:53)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:33)
    at javafx.event.Event.fireEvent(Event.java:171)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3311)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3151)
    at javafx.scene.Scene$MouseHandler.access$1900(Scene.java:3106)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1563)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2248)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:250)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:173)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:292)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:530)
    at com.sun.glass.ui.View.notifyMouse(View.java:924)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication$3$1.run(GtkApplication.java:89)
    at java.lang.Thread.run(Thread.java:724)
Caused by: java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:75)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:279)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1446)
    ... 43 more
Caused by: java.lang.IllegalStateException: Application launch must not be called more than once
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:94)
    at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:75)
    at javafx.application.Application.launch(Application.java:148)
    at program.Main.handleLoadButton(Main.java:35)
    ... 53 more

And hey, thanks everyone helping me out!

Was it helpful?

Solution

Your problem is, that you use your Application class as controller. That means the FXMLLoader tries to create another instance of Main. You have to create a different class for the controller.

Your modified Main class:

import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    private Stage myStage;

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


    @Override
    public void start(Stage stage) throws Exception {
        FXMLLoader loader = new FXMLLoader();

        // this creates a instance of Controller now
        // and not a instance of Main
        Parent root = (Parent) loader.load(getClass().getResourceAsStream("load.fxml"));

        // get the controller corresponding to root
        Controller controller = loader.getController();

        // tell the controller that this is it's Main class
        controller.setMain(this);

        stage.setTitle("FXML Welcome");
        stage.setScene(new Scene(root, 300, 275));
        stage.show();

        myStage = stage;
    }

    public void handleLoadButton() throws IOException {
        Parent root = FXMLLoader.load(getClass().getResource("main.fxml"));

        myStage.setTitle("FXML Main");
        myStage.setScene(new Scene(root, 300, 275));
        myStage.show();
    }
}

The controller class:

import java.io.IOException;
import javafx.fxml.FXML;

public class Controller {

    @FXML
    private void handleLoadButton() throws IOException {
        myMain.handleLoadButton();
    }

    private Main myMain;

    public void setMain(Main myMain) {
        this.myMain = myMain;
    }

}

Of course you have to replace the controller class in load.fxml:

The fx:controller attribute in the Root node of the file should be:

fx:controller="Controller"

you may have to add the package name, if you're not using the default package.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top