Как установить прослушиватель действия на кнопку Dialog OK из класса основного контроллера - PullRequest
0 голосов
/ 25 мая 2020

Я действительно хочу, чтобы кнопка ОК реагировала только тогда, когда все поля в диалоговом окне заполнены. И я также не предпочитаю отключать кнопку ОК.

Это метод из MainController, который устанавливает Dialog:

public void showItemDialog(){

    Dialog<ButtonType> dialog = new Dialog<>();
    FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("todoItemDialog.fxml"));
    try {
        dialog.getDialogPane().setContent(fxmlLoader.load());
    } catch (IOException e){
        System.out.println("Couldn't load Dialog");
    }

    dialog.getDialogPane().getButtonTypes().add(ButtonType.OK);
    dialog.getDialogPane().getButtonTypes().add(ButtonType.CANCEL);

    Optional<ButtonType> result = dialog.showAndWait();

    if(result.isPresent() && result.get() == ButtonType.OK){
        DialogController controller = fxmlLoader.getController();
        controller.processResults();
    }

}

А это мой класс DialogController:

public class DialogController {
@FXML
private TextField descriptionTextField;
@FXML
private TextArea detailsTextArea;
@FXML
private DatePicker deadlinePicker;
@FXML
private DialogPane dialogPaneId;

public void processResults(){
    String description = descriptionTextField.getText();
    String details = detailsTextArea.getText();
    LocalDate date = deadlinePicker.getValue();

    TodoData.getInstance().addTodoItem(new TodoItem(description, details, date));
}

public boolean areFieldsEmpty(){

    //checks if fields are empty...

    return (descriptionTextField.getText().trim().isEmpty() || detailsTextArea.getText().trim().isEmpty() ||
            deadlinePicker.getValue() == null);
}

}

Теперь я думаю, что кнопка EventHandler for OK должна выглядеть примерно так:

Button okButton = (Button) dialogPaneId.lookupButton(ButtonType.OK);
    okButton.addEventFilter(ActionEvent.ACTION, new EventHandler<ActionEvent>() {
        @Override
        public void handle(ActionEvent event) {
            System.out.println("was here");
            if(areFieldsEmpty()){
                event.consume();
            }
        }
    });

Но это не работает в классе MainController или в классе DialogController (показывает NullPointerException). Я новичок в JavaFX, также я много искал его здесь, но не смог найти какой-либо конкретный результат c. Заранее спасибо.

1 Ответ

0 голосов
/ 26 мая 2020

Я думаю, что в этом случае вам не стоит работать с функционалом Dialog. Вот небольшой пример того, как это можно сделать:

Класс MainController:

package sample;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;

import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

public class MainController implements Initializable {

    @Override
    public void initialize(URL location, ResourceBundle resources) {
        //...
    }

    @FXML
    public void handleShowDialogBtnClick(ActionEvent event) {
        FXMLLoader loader = new FXMLLoader(getClass().getResource("ToDoItem.fxml"));
        Parent root = null;
        try {
            root = loader.load();
        } catch (IOException ex) {
            System.err.println(ex.getMessage());
        }
        if (root == null) return;
        Stage toDoItemStage = new Stage();
        toDoItemStage.setTitle("My Dialog Title");
        toDoItemStage.setAlwaysOnTop(true);
        ToDoItemController toDoItemController = loader.getController();
        toDoItemStage.setScene(new Scene(root));
        toDoItemStage.initOwner((((Button) event.getSource()).getScene().getWindow()));
        toDoItemController.setStage(toDoItemStage);
        toDoItemStage.setOnCloseRequest(e -> toDoItemController.removeController());
        toDoItemStage.show();
    }
}

Main F XML Файл:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>


<Button onAction="#handleShowDialogBtnClick" text="Show Dialog" xmlns="http://javafx.com/javafx/11.0.1"
        xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.MainController"/>

Класс ToDoItemController:

package sample;

import javafx.fxml.FXML;
import javafx.fxml.LoadException;
import javafx.scene.control.*;
import javafx.stage.Stage;

public class ToDoItemController {

    @FXML
    private TextField
            descriptionTextField;
    @FXML
    private DatePicker
            deadlineDatePicker;
    @FXML
    private TextArea
            detailsTextArea;

    private Stage toDoItemStage;

    private static ToDoItemController toDoItemController;

    public ToDoItemController() throws LoadException {
        if (toDoItemController == null) toDoItemController = this;
        else throw new LoadException("Singleton FXML");
    }

    @FXML
    public void handleOkayBtnClick() {
        if (descriptionTextField.getText().trim().isEmpty()
                || detailsTextArea.getText().trim().isEmpty()
                || deadlineDatePicker.getValue() == null) {
            Alert alert = new Alert(Alert.AlertType.ERROR, "Some information is missing.", ButtonType.OK);
            alert.initOwner(toDoItemStage);
            alert.showAndWait();
        } else {
            TodoData.getInstance().addTodoItem(new TodoItem(description.get(), details.get(), deadline.get()));
            closeStage();
        }
    }

    @FXML
    public void handleCancelBtnClick() {
        closeStage();
    }

    void setStage(Stage toDoItemStage) {
        this.toDoItemStage = toDoItemStage;
    }

    void removeController() {
        toDoItemController = null;
    }

    private void closeStage() {
        removeController();
        toDoItemStage.close();
    }
}

ToDoItem F XML Файл:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.DatePicker?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>

<GridPane fx:id="rootGridPane" hgap="3.0" vgap="3.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/11.0.1" fx:controller="sample.ToDoItemController">
  <columnConstraints>
    <ColumnConstraints hgrow="ALWAYS" />
    <ColumnConstraints hgrow="NEVER" />
  </columnConstraints>
  <rowConstraints>
      <RowConstraints minHeight="10.0" vgrow="NEVER" />
    <RowConstraints minHeight="10.0" vgrow="NEVER" />
      <RowConstraints minHeight="10.0" vgrow="NEVER" />
    <RowConstraints minHeight="10.0" vgrow="NEVER" />
      <RowConstraints minHeight="10.0" vgrow="ALWAYS" />
      <RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
  </rowConstraints>
   <children>
      <HBox GridPane.columnSpan="2">
         <children>
            <Label text="My Custom Dialog">
               <font>
                  <Font size="24.0" />
               </font>
            </Label>
         </children>
      </HBox>
      <Label text="Description:" GridPane.rowIndex="1" />
      <TextField fx:id="descriptionTextField" GridPane.rowIndex="2" />
      <Label text="Details:" GridPane.rowIndex="3" />
      <TextArea fx:id="detailsTextArea" GridPane.columnSpan="2" GridPane.rowIndex="4" />
      <Label text="Deadline:" GridPane.columnIndex="1" GridPane.rowIndex="1" />
      <DatePicker fx:id="deadlineDatePicker" GridPane.columnIndex="1" GridPane.rowIndex="2" />
      <HBox alignment="CENTER_RIGHT" spacing="10.0" GridPane.columnSpan="2" GridPane.rowIndex="5">
         <children>
            <Button defaultButton="true" onAction="#handleOkayBtnClick" prefWidth="70.0" text="OK" />
            <Button cancelButton="true" onAction="#handleCancelBtnClick" prefWidth="70.0" text="Cancel" />
         </children>
      </HBox>
   </children>
   <padding>
      <Insets bottom="3.0" left="3.0" right="3.0" top="3.0" />
   </padding>
</GridPane>

Класс MainApplication:

package sample;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("Main.fxml"));
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...