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.
Post the stack trace in the question. Two things seem immediately wrong: 1. You are instantiating the controller class (
AccountDialog
) but you also havefx: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?
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 standardStage
, or use a pre-definedDialog
subclass. TheDialog
documentation states this: “It is likely that most developers would be better served using either theAlert
class (for pre-defined, notification-style alerts), or either of the two pre-built dialogs (TextInputDialog
andChoiceDialog
), depending on their needs.”. ExtendingDialog
yourself using FXML is a complex task.You don’t show the stack trace, but I would guess the
fx:controller="...AccountDialog"
attribute in the FXML file is the problem. TheFXMLLoader
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 callloader.setController(this)
.