So i try to dynamically load content into the center of a BorderPane when i click on a label in the left part but it doesnt show up. In the MRE ist doesnt show up at all. In the bigger project after some random clicks and when the right stars align, all of a sudden it will popup, but i dont know why. There are no compiler errors or runtime errors, so i cant help with that. Here it is said that you cant fill fields with new content and expect it to be shown but i always call the setCenter method, so i dont think thats the problem here.
App.java
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 App extends Application {
private static Scene scene;
@Override
public void start(Stage stage) throws IOException {
scene = new Scene(loadFXML("useradmin"), 800, 600);
stage.setScene(scene);
stage.show();
}
private static Parent loadFXML(String fxml) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(App.class.getResource(fxml + ".fxml"));
//fxmlLoader.setController(new CTRLuseradd());
return fxmlLoader.load();
}
public static void main(String[] args) {
launch();
}
static void setRoot(String fxml) throws IOException {
scene.setRoot(loadFXML(fxml));
}
}
useradmin.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.RowConstraints?>
<BorderPane xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1"
fx:id="userpane" fx:controller="CTRLuseradmin">
<left>
<GridPane>
<rowConstraints>
<RowConstraints vgrow="ALWAYS" minHeight="30" maxHeight="50"/>
</rowConstraints>
<columnConstraints>
<ColumnConstraints hgrow="ALWAYS" minWidth="20"/>
<ColumnConstraints hgrow="ALWAYS" halignment="LEFT"/>
<ColumnConstraints hgrow="ALWAYS" halignment="RIGHT"/>
<ColumnConstraints hgrow="ALWAYS" minWidth="20"/>
</columnConstraints>
<children>
<Label GridPane.halignment="LEFT"
GridPane.columnSpan="2" GridPane.rowIndex="1" GridPane.columnIndex="1"
text="+ Add user"
onMouseClicked="#showAddUserPane"/>
</children>
</GridPane>
</left>
<center>
<Pane fx:id="userboxEditarea"></Pane>
</center>
</BorderPane>
CTRLuseradmin.java
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.Pane;
public class CTRLuseradmin implements Initializable {
@FXML
private BorderPane userpane;
@FXML
private Pane userboxEditarea;
@FXML
private void showAddUserPane() {
CTRLuseradd addController = new CTRLuseradd();
FXMLLoader fxmlUserLoader = new FXMLLoader(
CTRLuseradmin.class.getResource("useradd.fxml"));
fxmlUserLoader.setController(addController);
try {
this.userboxEditarea = (Pane) (new Scene(fxmlUserLoader.load(), 0, 0)).getRoot();
addController.setAddPane(this.userboxEditarea);
} catch (IOException ex) {
ex.printStackTrace();
return;
}
this.userpane.setCenter(this.userboxEditarea);
}
@Override
public void initialize(URL location, ResourceBundle resources) {
}
}
useradd.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.ColumnConstraints?>
<Pane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/17">
<GridPane>
<columnConstraints>
<ColumnConstraints minWidth="200" hgrow="ALWAYS"/>
<ColumnConstraints minWidth="200" prefWidth="200" maxWidth="300" />
<ColumnConstraints minWidth="50" prefWidth="50" maxWidth="100" />
<ColumnConstraints minWidth="200" prefWidth="200" maxWidth="300" />
<ColumnConstraints minWidth="200" hgrow="ALWAYS"/>
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="50.0" maxHeight="100.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="20.0" maxHeight="50.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="20.0" maxHeight="50.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="20.0" maxHeight="50.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="50.0" maxHeight="100.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label GridPane.columnIndex="0"/>
<Label GridPane.rowIndex="0" GridPane.columnIndex="1" text="New user"/>
<Label GridPane.rowIndex="1" GridPane.columnIndex="1" text="username"/>
<TextField GridPane.rowIndex="1" GridPane.columnIndex="3" promptText="username"/>
<Label GridPane.rowIndex="2" GridPane.columnIndex="1" text="role"/>
<ChoiceBox GridPane.rowIndex="2" GridPane.columnIndex="3"/>
<Label GridPane.rowIndex="3" GridPane.columnIndex="1" text="password"/>
<PasswordField GridPane.rowIndex="3" GridPane.columnIndex="3" promptText="password"/>
<Button GridPane.rowIndex="4" GridPane.columnIndex="1" text="save"/>
<Button GridPane.rowIndex="4" GridPane.columnIndex="3" text="cancel"
onMouseClicked="#cancel" cancelButton="true"/>
<Label GridPane.columnIndex="3"/>
</children>
</GridPane>
</Pane>
CTRLuseradd.java
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.layout.Pane;
public class CTRLuseradd implements Initializable {
private Pane addPane;
@Override
public void initialize(URL location, ResourceBundle resources) {
}
public void setAddPane(Pane addpane2) { this.addPane = addpane2; }
@FXML
private void cancel() {
if (this.addPane != null) this.addPane.getChildren().clear();
}
}
When i put the code from useradd.fxml into the center part of the borderpane in useradmin.fxml everything works fine but that isnt what i want as there are supposed to be more clickable labels and the center part should be dynamically filled. Any help is gladly appreciated
The way you load your FXML is strange, you do this:
this.userboxEditarea = (Pane) (new Scene(fxmlUserLoader.load(), 0, 0)).getRoot();
Which does not do what you expect.
If instead, you do this, it will work:
this.userboxEditarea = fxmlUserLoader.load();
Explanation
There is no need to create a new scene when loading a new FXML file.
What you are doing is creating a scene, setting the newly loaded fxml as the root of the scene, then getting the root of the new scene and trying to use that same node in your previously existing scene. You can't do that because the node is already associated with a scene and a node can only appear once in a scene graph (no matter which scene it is associated with).
Instead, all you need to do is to load the new node from FXML and set it as the center of your border pane, which you are already doing in your existing code:
this.userpane.setCenter(this.userboxEditarea);
There are some other restructuring and simplification tasks you could do with the provided code, but that is subjective, tricky to explain, and not related to your core issue; so I won't discuss other optimizations here.