Search code examples
javajavafxjavafx-8fxmlfxmlloader

How to load new FXML with another controller class in the same scene


I've tried to load new FXML by

URL url = this.getClass().getClassLoader().getResource("pknn/fxml/CreateCharacter.fxml");if (url == null) return;
AnchorPane pane = FXMLLoader.load(url);
startPanel.getChildren().setAll(pane);

Which is worked for CreateCharacter.fxml with StartController

<AnchorPane fx:id="createCharacterPanel" onMouseEntered="#paneEventHandler" prefHeight="600.0" prefWidth="800.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="pknn.StartController">

But when I try to load another FXML to the same scene

URL url = this.getClass().getClassLoader().getResource("pknn/fxml/LockerRoom.fxml");
if (url == null) return;
AnchorPane pane = FXMLLoader.load(url);
createCharacterPanel.getChildren().setAll(pane);

it doesn't work, even I change it to

startPanel.getChildren().setAll(pane);

But it still not work. This is the fxml I want to load.

<AnchorPane fx:id="lockerRoomPane" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="pknn.LockerRoomController">

it come with so many exception like

Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
...
Caused by: javafx.fxml.LoadException: 
/Users/pknn/Study/ComPro/MonsterBattle/out/production/MonsterBattle/pknn/fxml/LockerRoom.fxml:10

at pknn.StartController.createCharacter(StartController.java:132)
Caused by: java.lang.IllegalAccessException: Class sun.reflect.misc.ReflectUtil can not access a member of class pknn.LockerRoomController with modifiers ""

How to fix it? Thanks


Solution

  • This is an example of loading different FXML frames in the same Scene

    create_character.fxml

    <AnchorPane fx:id="createCharacterPanel" fx:controller="sample.StartController" xmlns:fx="http://javafx.com/fxml" >
        <children>
            <Button text="Load" onAction="#handleLoadFXML" AnchorPane.topAnchor="0" AnchorPane.leftAnchor="0" />
            <ScrollPane AnchorPane.topAnchor="30" AnchorPane.leftAnchor="0" AnchorPane.rightAnchor="0" AnchorPane.bottomAnchor="0">
                <content>
                    <VBox fx:id="child"/>
                </content>
            </ScrollPane>
        </children>
    </AnchorPane>
    

    pane_a.fxml and pane_b.fxml

    <AnchorPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="sample.SecondController">
        <children>
            <Label text="Pane A"/>
        </children>
    </AnchorPane>
    
    <AnchorPane xmlns="http://javafx.com/javafx" xmlns:fx="http://javafx.com/fxml" fx:controller="sample.SecondController">
        <children>
            <Label text="Pane B"/>
        </children>
    </AnchorPane>
    

    The controller that loads the files

    public class StartController {
        @FXML
        private AnchorPane createCharacterPanel;
    
        @FXML
        private VBox child;
    
        private Parent loadFXML(String name) {
            try {
                return FXMLLoader.load(getClass().getResource(name));
            }
            catch (IOException e) {
                e.printStackTrace();
            }
    
            return null;
        }
    
        @FXML
        private void handleLoadFXML(ActionEvent event) {
            child.getChildren().addAll(
                loadFXML("pane_a.fxml"),
                loadFXML("pane_b.fxml")
            );
        }
    }