Is there any way to load my .fxml after i call the class of my dialog controller?

I’m trying to call my dialog with a form inside it thats contain label to put name and button of sign in and cancel and it seems i got an exception when i load my fxml for the dialog.

additional question:

  • On the AccountDialog, where a button get added to the dialogpane, any way hot to change the “OK” to “Sign In”?
  • How to add an image for the background of my dialogpane?
// MainController where onLogin is handling the event
public class PlayerController {
    @FXML
    private Label userName;
    @FXML
    private BorderPane mainBorderPane;

    @FXML
    public void onLogin(ActionEvent e) {
        Dialog<Account> dialog = new AccountDialog(new Account(""));
        dialog.initOwner(mainBorderPane.getScene().getWindow());
        Optional<Account> result = dialog.showAndWait();
        result.ifPresent(account -> {
            userName.setText(account.getName());
        });
    }
}
// fxml file for PlayerController
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>

<BorderPane fx:id="mainBorderPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/21" xmlns:fx="http://javafx.com/fxml/1" fx:controller="hi.project.vidmot.audioplayer.PlayerController">
   <center>
      <GridPane prefWidth="500.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="0.0" prefHeight="0.0" valignment="BOTTOM" vgrow="NEVER" />
          <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
        </rowConstraints>
         <children>
            <Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Playlist 1" GridPane.columnIndex="0" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS" />
            <Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Playlist2" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.vgrow="ALWAYS" />
            <Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Playlist3" GridPane.hgrow="ALWAYS" GridPane.rowIndex="2" GridPane.vgrow="ALWAYS" />
            <Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Playlist4" GridPane.columnIndex="1" GridPane.hgrow="ALWAYS" GridPane.rowIndex="2" GridPane.vgrow="ALWAYS" />
         </children>
      </GridPane>
   </center>
   <left>
      <VBox BorderPane.alignment="CENTER">
         <children>
            <Button onAction="#onLogin" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Sign in" />
            <Label fx:id="userName" alignment="CENTER" maxWidth="1.7976931348623157E308" prefHeight="35.0" prefWidth="100.0" text="Name" />
            <ScrollPane hbarPolicy="NEVER" prefWidth="100.0" vbarPolicy="ALWAYS" VBox.vgrow="ALWAYS" />
         </children>
      </VBox>
   </left>
</BorderPane>

// DialogController processing all things for the dialog
public class AccountDialog extends Dialog<Account> {
    private Account player;
    @FXML
    private TextField name;
    @FXML
    private GridPane gridPane;


    public AccountDialog(Account player) {
        super();
        this.setTitle("Sign in");
        readDialog();
        this.player = player;
    }

    private void readDialog(){
        FXMLLoader fxmlLoader = new FXMLLoader();
        fxmlLoader.setLocation(getClass().getResource("account-view.fxml"));
        try {
            this.getDialogPane().setContent(fxmlLoader.load());
        } catch (IOException e) {
            System.out.println("Couldn't load the dialog");
            e.printStackTrace();
        }

        this.getDialogPane().getButtonTypes().add(ButtonType.OK);
        this.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);
    }

}
// fxml file for Dialog scene
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<DialogPane xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="hi.project.vidmot.audioplayer.AccountDialog">

    <content>
        <GridPane vgap="10" hgap="10">
            <Label text="Name: " GridPane.rowIndex="0" GridPane.columnIndex="0"/>
            <TextField fx:id="name" GridPane.rowIndex="0" GridPane.columnIndex="1"/>
        </GridPane>
    </content>

</DialogPane>

Let’s say i click a button and i want it showing the dialogpane with form on it and an image background.

  • 2

    Post the stack trace in the question. Two things seem immediately wrong: 1. You are instantiating the controller class (AccountDialog) but you also have fx:controller=“…AccountDialog”, which will cause the FXML loader to create another instance of the controller class. The @FXML-annotated fields will be initialized in the second instance, not the first. 2. You don’t seem a converter anywhere, unless I am missing something. The documentation explicitly talks about this (under “Critical Note”)

    – 




  • ’On the AccountDialog, where a button get added to the dialogpane, any way hot to change the “OK” to “Sign In”?’ The documentation linked above also has code examples for this. Did you try that approach?

    – 

  • 3

    Please ask one question per question, not additional questions in a single question.

    – 

  • I advise not to use the Dialog class unless you need its specific functionality. Instead, create a standard Stage, or use a pre-defined Dialog subclass. The Dialog documentation states this: “It is likely that most developers would be better served using either the Alert class (for pre-defined, notification-style alerts), or either of the two pre-built dialogs (TextInputDialog and ChoiceDialog), depending on their needs.”. Extending Dialog yourself using FXML is a complex task.

    – 




  • 1

    You don’t show the stack trace, but I would guess the fx:controller="...AccountDialog" attribute in the FXML file is the problem. The FXMLLoader is trying to create an instance of the specified class, but since that class does not have a no-argument constructor and the loader is using the default controller factory, the loader has no idea how to create the instance. That’s in addition to the issues described in James_D’s comment. Remove that attribute from the FXML file and instead call loader.setController(this).

    – 

Leave a Comment