Error switching Scenes with FXML

848 Views Asked by At

So I want so switch the Scene between two FXML Files, but I get this error if I try to start the application:

Exception in Application start method
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:389)
at com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:328)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:767)
Caused by: java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$155(LauncherImpl.java:182)
at java.lang.Thread.run(Thread.java:745)
Caused by: javafx.fxml.LoadException: Error resolving onAction='#handleButtonAction', either the event handler is not in the Namespace or there is an error in the script.

 /C:/Users/j3Ypi/Dropbox/05_Praktikum/survey/out/production/survey/survey/view/moduleA.fxml:28
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2597)
at javafx.fxml.FXMLLoader.access$100(FXMLLoader.java:103)
at javafx.fxml.FXMLLoader$Element.processEventHandlerAttributes(FXMLLoader.java:610)
at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:770)
at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2823)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2532)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
at survey.Main.showModuleA(Main.java:40)
at survey.Main.start(Main.java:24)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$162(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$175(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
... 1 more
Exception running application survey.Main 

I tried several approaches to load the FXML file, but each time the same error occurs. I also tried multiple potential solutions suggested by the community here but none seems to fix my problem. Most of them said it'd be a matter of the correct path, but I load the exact same path in the controller as in the main app and without handleButtonAction() in the controller the applications starts properly. I'm stuck on this basic task for hours now. I use IDEA and here's my code:

Main:

package survey;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

import java.io.IOException;

public class Main extends Application {

private Stage primaryStage;
private BorderPane rootLayout;

@Override
public void start(Stage primaryStage) throws Exception{
    this.primaryStage = primaryStage;
    this.primaryStage.setTitle("Modul A");

    initRootlayout();

    showModuleA();
}

private void  initRootlayout() throws IOException{
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(Main.class.getResource("view/rootLayout.fxml"));
        rootLayout = loader.load();

        Scene scene = new Scene(rootLayout);
        primaryStage.setScene(scene);
        primaryStage.show();
}

private void showModuleA() throws IOException {
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(Main.class.getResource("view/moduleA.fxml"));
        AnchorPane rootPane = loader.load();

        rootLayout.setCenter(rootPane);
}


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

Controller:

package survey.view;

import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;

import java.awt.event.ActionEvent;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

public class moduleAController implements Initializable {

@FXML private Button bBack;
@FXML private Button bForward;

@FXML
private void handleButtonAction(ActionEvent event) throws IOException{

    Stage stage;
    Parent root;

    if (event.getSource() == bBack){
        stage = (Stage) bBack.getScene().getWindow();
        root = FXMLLoader.load(getClass().getResource("view/moduleB.fxml"));
    } else {
        stage = (Stage) bForward.getScene().getWindow();
        root = FXMLLoader.load(getClass().getResource("view/moduleA.fxml"));
    }

    Scene scene = new Scene(root);
    stage.setScene(scene);
    stage.show();

}

@Override
public void initialize(URL location, ResourceBundle resources) {

}
}

FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.RadioButton?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.ToggleGroup?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>

<AnchorPane fx:id="rootPane" prefHeight="470.0" prefWidth="950.0" styleClass="background" stylesheets="@DarkTheme.css" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="survey.view.moduleAController">
   <children>
      <BorderPane layoutX="12.0" prefHeight="470.0" prefWidth="950.0">
         <top>
            <GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="62.0" prefWidth="450.0" BorderPane.alignment="BOTTOM_RIGHT">
              <columnConstraints>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
          </columnConstraints>
              <rowConstraints>
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
          </rowConstraints>
               <children>
                  <Button fx:id="bBack" mnemonicParsing="false" onAction="#handleButtonAction" prefHeight="30.0" prefWidth="110.0" text="Zurück" GridPane.columnIndex="1" />
                  <Button fx:id="bForward" mnemonicParsing="false" onAction="#handleButtonAction" prefHeight="30.0" prefWidth="110.0" text="Vorwärts" GridPane.columnIndex="2" />
                  <Label fx:id="lModul" text="Modul:" GridPane.halignment="CENTER" GridPane.valignment="CENTER" />
           </children>
        </GridPane>
     </top>
         <left>
            <GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="100.0" BorderPane.alignment="CENTER">
              <columnConstraints>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
          </columnConstraints>
              <rowConstraints>
                  <RowConstraints maxHeight="126.0" minHeight="10.0" prefHeight="95.0" vgrow="SOMETIMES" />
                <RowConstraints maxHeight="126.0" minHeight="10.0" prefHeight="95.0" vgrow="SOMETIMES" />
                <RowConstraints maxHeight="180.0" minHeight="10.0" prefHeight="104.0" vgrow="SOMETIMES" />
                <RowConstraints maxHeight="253.0" minHeight="10.0" prefHeight="95.0" vgrow="SOMETIMES" />
          </rowConstraints>
               <children>
                  <Label fx:id="lFrageA" text="1. Frage A" GridPane.halignment="CENTER" GridPane.rowIndex="1" />
                  <Label fx:id="lFrageB" text="2. Frage B" GridPane.halignment="CENTER" GridPane.rowIndex="2" />
                  <Label fx:id="lFrageC" text="3. Frage C" GridPane.halignment="CENTER" GridPane.rowIndex="3" />
              <Label text="Modul A" GridPane.halignment="CENTER" />
           </children>
        </GridPane>
     </left>
         <center>
            <GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="189.0" BorderPane.alignment="CENTER">
              <columnConstraints>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
          </columnConstraints>
              <rowConstraints>
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
          </rowConstraints>
               <children>
                  <RadioButton fx:id="bCheckA1" mnemonicParsing="false" GridPane.halignment="CENTER" GridPane.rowIndex="1">
                     <toggleGroup>
                        <ToggleGroup fx:id="groupA" />
                 </toggleGroup>
              </RadioButton>
                  <RadioButton fx:id="bCheckA2" mnemonicParsing="false" toggleGroup="$groupA" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="1" />
                  <RadioButton fx:id="bCheckB1" mnemonicParsing="false" GridPane.halignment="CENTER" GridPane.rowIndex="2">
                     <toggleGroup>
                        <ToggleGroup fx:id="groupB" />
                 </toggleGroup></RadioButton>
                  <RadioButton fx:id="bCheckB2" mnemonicParsing="false" toggleGroup="$groupB" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="2" />
                  <RadioButton fx:id="bCheckC1" mnemonicParsing="false" GridPane.halignment="CENTER" GridPane.rowIndex="3">
                     <toggleGroup>
                        <ToggleGroup fx:id="groupC" />
                 </toggleGroup></RadioButton>
                  <RadioButton fx:id="bCheckC2" mnemonicParsing="false" toggleGroup="$groupC" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="3" />
                  <Label fx:id="lTrue" text="trifft zu" GridPane.halignment="CENTER" />
                  <Label fx:id="lFalse" text="trifft nicht zu" GridPane.columnIndex="1" GridPane.halignment="CENTER" />
           </children>
        </GridPane>
     </center>
         <bottom>
            <GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="62.0" prefWidth="600.0" BorderPane.alignment="BOTTOM_CENTER">
              <columnConstraints>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                  <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
          </columnConstraints>
              <rowConstraints>
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
          </rowConstraints>
               <children>
                  <Button mnemonicParsing="false" prefHeight="30.0" prefWidth="160.0" text="Neue Befragung" GridPane.halignment="CENTER" />
                  <Button fx:id="bSave" mnemonicParsing="false" prefHeight="30.0" prefWidth="130.0" text="Speichern" GridPane.columnIndex="1" GridPane.halignment="CENTER" />
                  <Button mnemonicParsing="false" prefHeight="30.0" prefWidth="130.0" text="Auswertung" GridPane.columnIndex="2" GridPane.halignment="CENTER" />
           </children>
        </GridPane>
     </bottom>
         <right>
            <GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="300.0" prefWidth="300.0" BorderPane.alignment="CENTER_RIGHT">
              <columnConstraints>
                <ColumnConstraints hgrow="SOMETIMES" maxWidth="-Infinity" minWidth="10.0" prefWidth="100.0" />
          </columnConstraints>
              <rowConstraints>
                  <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
               <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
          </rowConstraints>
               <children>
                  <TextArea maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="70.0" prefWidth="250.0" GridPane.rowIndex="1" />
                  <TextArea maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="70.0" prefWidth="250.0" GridPane.rowIndex="2" />
                  <TextArea maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="70.0" prefWidth="250.0" GridPane.rowIndex="3" />
                  <Label text="Kommentar" />
           </children>
        </GridPane>
     </right>
  </BorderPane>
</children>
</AnchorPane>

I appreciate any help. Thanks in advance!

EDIT: In addition to the wrong import of Action Event there was a mistake in the path. The Controller is located in the view folder so the path is just moduleB.fxml not view/moduleB.fxml.

Thanks for the help!

1

There are 1 best solutions below

1
On BEST ANSWER

The solution for your second problem is the following:

root = FXMLLoader.load(getClass().getClassLoader().getResource("xxx/yyy/view/moduleB.fxml)"

where xxx and yyy is the package structure from your java project. For example src/foo/var/view/moduleB.fxml -> "foo/var/view/moduleB.fxml"

The reason why is you are trying to load it at runtime, and you need to add getClassLoader() else you will get the actual class path from the controller because you are calling the getClass() method in the controller. This is the reason why it cant find your fxml file. It expects it being in the view package underlying the package of your controller. I hope it works now :)

First Problem:

You got a little error in your controller script. You imported the wrong ActionEvent. You imported

import java.awt.event.ActionEvent;

but need to import

import javafx.event.ActionEvent;

This should fix it.