在对话框上执行字段检查时未显示 JavaFX 警报

JavaFX Alert not showing up when performing a fields check on a Dialog

我是 JavaFX 的初学者,正在练习一个小型应用程序。问题是我试图在没有成功的情况下实现对对话框字段的检查(如果为空),如果是则填充警告类型的警报。 如果未填写所有字段,对话框确实不会输入数据,但永远不会显示警报。

这是主控制器代码:

  @FXML
    public void showAddReportDialog () {
        Dialog<ButtonType> dialog = new Dialog<ButtonType>();
        dialog.initOwner(mainPanel.getScene().getWindow());
        dialog.setTitle("Add new report");
        FXMLLoader fxmlLoader = new FXMLLoader();
        fxmlLoader.setLocation(getClass().getResource("addReportDialog.fxml"));
        try {
            dialog.getDialogPane().setContent(fxmlLoader.load());
        } catch (IOException e) {
            System.out.println("Could not load the dialog");
            e.printStackTrace();
            return;
        }
        dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
        dialog.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);
        final Button btOK = (Button) dialog.getDialogPane().lookupButton(ButtonType.OK);
        btOK.addEventFilter(ActionEvent.ACTION, event -> {
            AddDialogController addDialogController = fxmlLoader.getController();
            Report newReport = addDialogController.getNewReport();
            if (newReport != null) {
                data.addReport(newReport);
                data.saveReports();
            } else {
                event.consume();
            }
        });
        Optional<ButtonType> result = dialog.showAndWait();
    }

这是包含警报的对话框控制器代码:

public Report getNewReport() {
  String iD = iDField.getText();
  String name = nameField.getText();
  LocalDate dueDate = dueDateField.getValue();
  String recipients = recipientsField.getText();
  String notes = notesField.getText();

  String dueDateString = dueDate.toString();

  if (iDField.getText().equals("") || nameField.getText().equals("") || dueDateField.getValue() == null || recipientsField.getText().equals("") || notesField.getText().equals("")) {
    Alert alert = new Alert(Alert.AlertType.WARNING);
    alert.setTitle("Fields incomplete");
    alert.setHeaderText(null);
    alert.setContentText("Please complete all the form fields");
    alert.showAndWait();
    return null;
  } else {
    Report newReport = new Report(iD, name, dueDateString, recipients, notes);
    return newReport;
  }
}

非常感谢您的帮助!

您可以执行此操作,但 Dialog 将始终在 Alert 关闭后关闭。我建议将登录 Button 绑定到 TextFields.

你问题的答案:

import java.util.Optional;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar.ButtonData;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Pair;


/**
 * JavaFX App
 */
public class App extends Application {

    @Override
    public void start(Stage stage) {        
        Button button = new Button("Show Add Report Dialog");
        button.setOnAction((e) -> {
            showAddReportDialog();
        });

        StackPane layout = new StackPane();
        layout.getChildren().add(button);

        Scene scene = new Scene(layout, 300, 250);
        stage.setScene(scene);
        stage.show();
    }

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

    public void showAddReportDialog () {
        //Code from https://code.makery.ch/blog/javafx-dialogs-official/.
        Dialog<Pair<String, String>> dialog = new Dialog<>();
        dialog.setTitle("Login Dialog");
        dialog.setHeaderText("Look, a Custom Login Dialog");

        // Set the icon (must be included in the project).
        //dialog.setGraphic(new ImageView(this.getClass().getResource("login.png").toString()));

        // Set the button types.
        ButtonType loginButtonType = new ButtonType("Login", ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, ButtonType.CANCEL);

        // Create the username and password labels and fields.
        GridPane grid = new GridPane();
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(20, 150, 10, 10));

        TextField username = new TextField();
        username.setPromptText("Username");
        PasswordField password = new PasswordField();
        password.setPromptText("Password");

        grid.add(new Label("Username:"), 0, 0);
        grid.add(username, 1, 0);
        grid.add(new Label("Password:"), 0, 1);
        grid.add(password, 1, 1);

        // Enable/Disable login button depending on whether a username was entered.
        Node loginButton = dialog.getDialogPane().lookupButton(loginButtonType);
        //loginButton.setDisable(true);

        // Do some validation (using the Java 8 lambda syntax).
//        loginButton.disableProperty().bind(Bindings.createBooleanBinding(
//            () -> username.getText().isEmpty() || password.getText().isEmpty(),
//            username.textProperty(), password.textProperty()));

        dialog.getDialogPane().setContent(grid);

        // Request focus on the username field by default.
        Platform.runLater(() -> username.requestFocus());

        // Convert the result to a username-password-pair when the login button is clicked.
        dialog.setResultConverter(dialogButton -> {
            if (dialogButton == loginButtonType) {
                if(username.getText().isBlank() || password.getText().isBlank())
                {
                    Alert alert = new Alert(Alert.AlertType.WARNING);
                    alert.setTitle("Fields incomplete");
                    alert.setHeaderText(null);
                    alert.setContentText("Please complete all the form fields");
                    alert.showAndWait();
                }
                else
                {
                    return new Pair<String, String>(username.getText(), password.getText());
                }
                
            }
            
            return null;
        });

        Optional<Pair<String, String>> result = dialog.showAndWait();

        result.ifPresent(usernamePassword -> {
            System.out.println("Username=" + usernamePassword.getKey() + ", Password=" + usernamePassword.getValue());
        });
    }
}

我推荐的是:使用Bindings

import java.util.Optional;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonBar.ButtonData;
import javafx.scene.control.ButtonType;
import javafx.scene.control.Dialog;
import javafx.scene.control.Label;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
import javafx.util.Pair;


/**
 * JavaFX App
 */
public class App extends Application {

    @Override
    public void start(Stage stage) {        
        Button button = new Button("Show Add Report Dialog");
        button.setOnAction((e) -> {
            showAddReportDialog();
        });

        StackPane layout = new StackPane();
        layout.getChildren().add(button);

        Scene scene = new Scene(layout, 300, 250);
        stage.setScene(scene);
        stage.show();
    }

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

    public void showAddReportDialog () {
        //Code from https://code.makery.ch/blog/javafx-dialogs-official/.
        Dialog<Pair<String, String>> dialog = new Dialog<>();
        dialog.setTitle("Login Dialog");
        dialog.setHeaderText("Look, a Custom Login Dialog");

        // Set the icon (must be included in the project).
        //dialog.setGraphic(new ImageView(this.getClass().getResource("login.png").toString()));

        // Set the button types.
        ButtonType loginButtonType = new ButtonType("Login", ButtonData.OK_DONE);
        dialog.getDialogPane().getButtonTypes().addAll(loginButtonType, ButtonType.CANCEL);

        // Create the username and password labels and fields.
        GridPane grid = new GridPane();
        grid.setHgap(10);
        grid.setVgap(10);
        grid.setPadding(new Insets(20, 150, 10, 10));

        TextField username = new TextField();
        username.setPromptText("Username");
        PasswordField password = new PasswordField();
        password.setPromptText("Password");

        grid.add(new Label("Username:"), 0, 0);
        grid.add(username, 1, 0);
        grid.add(new Label("Password:"), 0, 1);
        grid.add(password, 1, 1);

        // Enable/Disable login button depending on whether a username was entered.
        Node loginButton = dialog.getDialogPane().lookupButton(loginButtonType);
        loginButton.setDisable(true);

        // Do some validation (using the Java 8 lambda syntax).
        loginButton.disableProperty().bind(Bindings.createBooleanBinding(
            () -> username.getText().isEmpty() || password.getText().isEmpty(),
            username.textProperty(), password.textProperty()));

        dialog.getDialogPane().setContent(grid);

        // Request focus on the username field by default.
        Platform.runLater(() -> username.requestFocus());

        // Convert the result to a username-password-pair when the login button is clicked.
        dialog.setResultConverter(dialogButton -> {
            if (dialogButton == loginButtonType) {               
                return new Pair<>(username.getText(), password.getText());
            }
            
            return null;
        });

        Optional<Pair<String, String>> result = dialog.showAndWait();

        result.ifPresent(usernamePassword -> {
            System.out.println("Username=" + usernamePassword.getKey() + ", Password=" + usernamePassword.getValue());
        });
    }
}