JavaFX NullpointerException с F XML в собственном диалоговом окне при попытке закрыть окно - PullRequest
1 голос
/ 24 апреля 2020

Я новичок в JavaFX. Я запрограммировал просмотр таблицы со списком лиц с их адресом. Все работало нормально Затем я хотел написать это в MVC или даже лучше в шаблоне MVP Design. Я работаю с F XML и сценостроителем, чтобы разметить сцены. Теперь с MVC у меня проблема в том, что я получаю NUllpointerException, когда я хочу закрыть диалоговое окно подтверждения. И я также не могу изменить текст метки для сцены окна подтверждения диалога. Я думаю, что знаю, в чем проблема, но не знаю, как решить это правильно. Контроллер создается дважды, и поэтому первые значения переменных из f xml равны NUll.

Вот как я написал свое маленькое приложение:

MiniTest. java - мое основное приложение


package AddressBook;

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

public class MiniTest extends Application {

    private static Stage window;

    @Override
    public void start(Stage primaryStage) throws Exception {

        window = primaryStage;
        window.setTitle("Adresslist of Clients");
        Model model = new Model();

        try {
            FXMLLoader mainViewloader = new FXMLLoader(getClass().getResource("View.fxml"));
            Parent root = (Parent) mainViewloader.load();
            MainController mainController = mainViewloader.<MainController>getController();

            window.setScene(new Scene(root));
            window.show();

        } catch (Exception e) {

            e.printStackTrace();
        }
    }

    public static Stage getPrimaryStage() {

        return window;
    }

    public static void main(String[] args) {

        launch(args);
    }
}

Модель. java - это моя модель , не уверен, что контент должен быть здесь. Для следующего шага я хочу собрать данные из mysql db и сохранить их в db. Пока у меня есть такие люди.

package AddressBook;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

public class Model {

    public ObservableList<Person> getPerson() {

        ObservableList<Person> personList = FXCollections.observableArrayList();

        Address addressPerson1 = new Address("Jaguarweg 12", "23454", "Bensheim");
        Address addressPerson2 = new Address("Friedrich-Ebert-Str. 134", "82635", "Berlin");
        Address addressPerson3 = new Address("Adam-Opel-Str. 1", "92364", "Bamberg");
        Address addressPerson4 = new Address("Power-Shell-Pfad 21", "10083", "Hamburg");
        Address addressPerson5 = new Address("Schwertstr. 76", "749236", "Stuttgart");
        Address addressPerson6 = new Address("Hans-Jacob-Weg 4", "66396", "Wiesbaden");
        Address addressPerson7 = new Address("Georg-Lucas-Str. 110", "53421", "Wien");
        Address addressPerson8 = new Address("Andalusienweg 17", "723612", "Ostfildern");
        Address addressPerson9 = new Address("Mercedes-Benz-Str. 9", "883621", "Wolfsburg");
        Address addressPerson10 = new Address("Heinrich-Schwein-Str. 43", "134923", "Frankfurt");
        Address addressPerson11 = new Address("Engel-Teufel-Str. 66", "083273", "Hildesheim");

        personList.add(new Person("Georg Sorresto", addressPerson1));
        personList.add(new Person("Flynn Bozzen", addressPerson2));
        personList.add(new Person("Bill Klang", addressPerson3));
        personList.add(new Person("Wilhelm Busch", addressPerson4));
        personList.add(new Person("Gertrud Raven", addressPerson5));
        personList.add(new Person("Markus Berg", addressPerson6));
        personList.add(new Person("Juergen Schmidt", addressPerson7));
        personList.add(new Person("Fritz Titz", addressPerson8));
        personList.add(new Person("Bodo Bambino", addressPerson9));
        personList.add(new Person("Ortrun Giner", addressPerson10));
        personList.add(new Person("Jakob Huber", addressPerson11));
        return personList;
    }
}

Person. java - мой класс Person

package AddressBook;

import javafx.beans.property.SimpleStringProperty;

public class Person {

    private SimpleStringProperty name;
    private Address address;

    public Person() {
        this.name = new SimpleStringProperty("");
        this.address = new Address("", "", "");
    }

    public Person(String name, Address address) {
        this.name = new SimpleStringProperty(name);
        ;
        this.address = address;
    }


    public String getName() {
        return name.get();
    }

    public void setName(String name2) {
        name.set(name2);
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }
}

в MainController. java - для определенных вещей, например, закрытие окна или для удаления человека я вызываю такой метод как мое собственное окно подтверждения с соответствующей строкой для метки.

        boolean answer = confirmDialogBoxController.display("Exiting Window", "Are you sure you want to close the window?");
        if (answer) {

            MiniTest.getPrimaryStage().close();
        }

и вот полный MainController. java - это mainController для mainView ( View.f xml)

package AddressBook;

import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;

import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import javafx.util.Callback;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

public class MainController implements Initializable {

    @FXML
    private MenuItem exitMenu;

    @FXML
    private TableView<Person> personTable;
    @FXML
    private TextField zipInput;
    @FXML
    private TextField cityInput;
    @FXML
    private TextField streetInput;
    @FXML
    private TextField nameInput;
    @FXML
    private TableColumn<Person, String> cityColumn;
    @FXML
    private TableColumn<Person, String> zipColumn;
    @FXML
    private TableColumn<Person, String> streetColumn;
    @FXML
    private TableColumn<Person, String> nameColumn;
    @FXML
    private Button addButton;
    @FXML
    private Button deleteButton;
    @FXML
    private SimpleStringProperty message;

    private Stage window;
    private ConfirmDialogBoxController confirmDialogBoxController;
    private AlertEmptyNameController alertEmptyNameController;
    private Model model;

    public MainController(){
        model = new Model();
        System.out.println("+1 MainController()");
    }
    public MainController(Model model){

        this.model = model;
        System.out.println("+1 MainController(model)");
    }



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

        Callback<TableColumn<Person, String>, TableCell<Person, String>> cellFactory = (TableColumn<Person, String> p) -> new MainController.EditingCell();

        nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
        nameColumn.setCellFactory(cellFactory);
        nameColumn.setOnEditCommit(
                (
                        TableColumn.CellEditEvent<Person, String> t) ->

                {
                    ((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).setName(t.getNewValue());
                }
        );

        streetColumn.setCellValueFactory(person -> new

                SimpleStringProperty(person.getValue().

                getAddress().

                getStreet()));
        streetColumn.setCellFactory(cellFactory);
        streetColumn.setOnEditCommit(
                (
                        TableColumn.CellEditEvent<Person, String> t) ->

                {
                    ((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).getAddress().setStreet(t.getNewValue());
                });

        zipColumn.setCellValueFactory(person -> new

                SimpleStringProperty(person.getValue().

                getAddress().

                getZip()));
        zipColumn.setCellFactory(cellFactory);
        zipColumn.setOnEditCommit(
                (
                        TableColumn.CellEditEvent<Person, String> t) ->

                {
                    ((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).getAddress().setZip(t.getNewValue());
                });

        cityColumn.setCellValueFactory(person -> new

                SimpleStringProperty(person.getValue().

                getAddress().

                getCity()));
        cityColumn.setCellFactory(cellFactory);
        cityColumn.setOnEditCommit(
                (
                        TableColumn.CellEditEvent<Person, String> t) ->

                {
                    ((Person) t.getTableView().getItems().get(t.getTablePosition().getRow())).getAddress().setCity(t.getNewValue());
                });
        personTable.setItems(model.getPerson());
        personTable.setEditable(true);


        MiniTest.getPrimaryStage().setOnCloseRequest(e -> {

            try {
                e.consume();
                closeWindow(e);
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        });
    }

    public SimpleStringProperty getMessageProperty(){

        return message;
    }

    public void setMessage(String message) {

        this.message.setValue(message);
    }

    public String getMessage() {

        return this.message.getValue();
    }


    @FXML
    public void closeWindow(WindowEvent e) throws IOException {

        boolean answer = confirmDialogBoxController.display("Exiting Window", "Are you sure you want to close the window?");
        if (answer) {

            MiniTest.getPrimaryStage().close();
        }
    }

    @FXML
    public void closeWindowFromMenu(ActionEvent e) throws IOException {

        boolean answer = confirmDialogBoxController.display("Exiting Window", "Are you sure you want to close the window?");
        if (answer) {

            MiniTest.getPrimaryStage().close();
        }
    }

    public Stage getPrimaryStage() {

        return window;
    }

    @FXML
    public void addNewPerson() throws IOException {

        alertEmptyNameController = new AlertEmptyNameController();
        Person person = new Person();
        person.setName(nameInput.getText());
        if(nameInput.getText().isEmpty()){
            alertEmptyNameController.alertEmptyName();
        }else{
        person.getAddress().setStreet(streetInput.getText());
        person.getAddress().setZip(zipInput.getText());
        person.getAddress().setCity(cityInput.getText());
        personTable.getItems().add(person);
        }
        nameInput.clear();
        streetInput.clear();
        zipInput.clear();
        cityInput.clear();
    }

    @FXML
    public void deletePerson() throws IOException {

        boolean answer = confirmDialogBoxController.display("Deleting Entry", "Are you sure you want to delete this entry?");
        if (answer) {
            ObservableList<Person> personSelected, allPersons;
            allPersons = personTable.getItems();
            personSelected = personTable.getSelectionModel().getSelectedItems();
            personSelected.forEach(allPersons::remove);
        }

    }

    static class EditingCell extends TableCell<Person, String> {

        private TextField textField;

        public EditingCell() {
        }

        @Override
        public void startEdit() {

            if (!isEmpty()) {
                super.startEdit();
                createTextField();
                setText(null);
                setGraphic(textField);
                textField.selectAll();
            }
        }

        @Override
        public void cancelEdit() {

            super.cancelEdit();
            setText((String) getItem());
            setGraphic(null);
        }

        @Override
        public void updateItem(String item, boolean empty) {

            super.updateItem(item, empty);

            if (empty) {
                setText(null);
                setGraphic(null);
            } else {
                if (isEditing()) {
                    if (textField != null) {
                        textField.setText(getString());
                    }
                    setText(null);
                    setGraphic(textField);
                } else {
                    setText(getString());
                    setGraphic(null);
                }
            }
        }

        private void createTextField() {

            textField = new TextField(getString());
            textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
            textField.focusedProperty().addListener((ObservableValue<? extends Boolean> arg0,
                                                     Boolean arg1, Boolean arg2) -> {
                if (!arg2) {
                    commitEdit(textField.getText());
                }
            });
        }

        private String getString() {
            return getItem() == null ? "" : getItem();
        }
    }
}

View.f xml - это основное представление

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

<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>


<BorderPane fx:id="borderPane" stylesheets="@MyStyle.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="AddressBook.MainController">
    <bottom>
        <HBox fx:id="bottomLayout" alignment="CENTER" style="-fx-background-color: #292929;" BorderPane.alignment="CENTER">
            <BorderPane.margin>
                <Insets />
            </BorderPane.margin>
            <children>
                <TextField fx:id="nameInput" promptText="Name" style="-fx-background-radius: 0;">
                    <HBox.margin>
                        <Insets bottom="8.0" left="8.0" right="5.0" top="10.0" />
                    </HBox.margin>
                </TextField>
                <TextField fx:id="streetInput" layoutX="15.0" layoutY="15.0" promptText="Street" style="-fx-background-radius: 0;">
                    <HBox.margin>
                        <Insets bottom="8.0" left="5.0" right="5.0" top="10.0" />
                    </HBox.margin>
                </TextField>
                <TextField fx:id="zipInput" layoutX="163.0" layoutY="15.0" promptText="Zip" style="-fx-background-radius: 0;">
                    <HBox.margin>
                        <Insets bottom="8.0" left="5.0" right="5.0" top="10.0" />
                    </HBox.margin>
                </TextField>
                <TextField fx:id="cityInput" layoutX="312.0" layoutY="15.0" promptText="City" style="-fx-background-radius: 0;">
                    <HBox.margin>
                        <Insets bottom="8.0" left="5.0" right="5.0" top="10.0" />
                    </HBox.margin>
                </TextField>
                <Button fx:id="addButton" mnemonicParsing="false" onAction="#addNewPerson" style="-fx-background-color: #5ebcff; -fx-background-radius: 0; -fx-text-fill: white;" text="Add">
                    <HBox.margin>
                        <Insets bottom="8.0" left="5.0" right="5.0" top="10.0" />
                    </HBox.margin>
                </Button>
                <Button fx:id="deleteButton" layoutX="474.0" layoutY="15.0" mnemonicParsing="false" onAction="#deletePerson" style="-fx-background-radius: 0; -fx-background-color: #5ebcff; -fx-text-fill: white;" text="Delete">
                    <HBox.margin>
                        <Insets bottom="8.0" left="5.0" right="8.0" top="10.0" />
                    </HBox.margin>
                </Button>
            </children>
        </HBox>
    </bottom>
    <center>
        <TableView fx:id="personTable" editable="true" style="-fx-background-color: #5e5e5e;" stylesheets="@MyStyle.css" BorderPane.alignment="CENTER">
            <columns>
                <TableColumn fx:id="nameColumn" prefWidth="152.0" text="Name" />
                <TableColumn fx:id="streetColumn" prefWidth="196.0" text="Street" />
                <TableColumn fx:id="zipColumn" prefWidth="88.0" text="Zip" />
                <TableColumn fx:id="cityColumn" prefWidth="163.0" text="City" />
            </columns>
        </TableView>
    </center>
    <top>
        <HBox fx:id="menuLayout" style="-fx-background-color: #292929;" stylesheets="@MyStyle.css" BorderPane.alignment="CENTER">
            <children>
                <MenuBar fx:id="menuBar" stylesheets="@MyStyle.css">
                    <menus>
                        <Menu fx:id="fileMenu" mnemonicParsing="false" text="File">
                            <items>
                                <MenuItem fx:id="exitMenu" mnemonicParsing="false" onAction="#closeWindowFromMenu" text="Exit" />
                            </items>
                        </Menu>
                    </menus>
                </MenuBar>
            </children>
        </HBox>
    </top>
</BorderPane>

ConfirmDialogBoxController. java - это контроллер для подтверждения диалоговое окно для закрытия окна с помощью "X" или в меню Файл-> Выход и для запроса пользователя, действительно ли он хочет удалить запись в табличном представлении

package AddressBook;

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.scene.control.Label;
import javafx.stage.Modality;
import javafx.stage.Stage;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;

public class ConfirmDialogBoxController implements Initializable {

    private static Boolean answer;
    @FXML
    private Button yesButton;
    @FXML
    private Button noButton;
    @FXML
    private Label confirmLabel;
    @FXML
    private Stage stage;
    @FXML
    private Model model;

    public ConfirmDialogBoxController(){

        System.out.println("+1 ConfirmDialogBoxController() object instantiated");
        }

    public ConfirmDialogBoxController(Model model){
        this.model = model;
        System.out.println("+1 ConfirmDialogBoxController(model) object instantiated");
}

    public boolean display(String title, String message) throws IOException {

        FXMLLoader confirmViewLoader = new FXMLLoader(getClass().getResource("ConfirmDialogBoxView.fxml"));
        confirmViewLoader.load();
        ConfirmDialogBoxController confirmDialogBoxController = confirmViewLoader.getController();
        confirmDialogBoxController.confirmLabel.setText(message);
        Parent root = confirmViewLoader.getRoot();
        Stage stage = new Stage();
        stage.setTitle(title);
        stage.setScene(new Scene(root));
        stage.initModality(Modality.APPLICATION_MODAL);
        System.out.println("MessageVariable in DisplayMethod is:"+message);
        stage.showAndWait();
        return answer;
    }

    public Label getLabel(){
        return confirmLabel;
    }

    @FXML
    public boolean yesButtonClicked(ActionEvent actionEvent) {

        answer = true;
        stage = (Stage) yesButton.getScene().getWindow();
        stage.close();
        return answer;
    }

    @FXML
    public boolean noButtonClicked(ActionEvent actionEvent) {

        answer = false;
        Stage confirmWindow = (Stage) noButton.getScene().getWindow();
        confirmWindow.close();
        return answer;
    }

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

//        confirmLabel.textProperty().bindBidirectional(messageProperty);
//        System.out.println("messageProperty.getValue(): "+ messageProperty.getValue());
//        System.out.println("DEBUG: message is = " + messageProperty.get());
    }
}

ConfirmDialogBoxView.f xml - это представление ConfirmDialogBox

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

<?import javafx.geometry.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane prefWidth="450.0" stylesheets="@MyStyle.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="AddressBook.ConfirmDialogBoxController">
   <children>
      <VBox fx:id="vBox" alignment="CENTER" spacing="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <children>
            <Label fx:id="confirmLabel"  textAlignment="CENTER" />
            <HBox fx:id="hBox" alignment="CENTER" spacing="10.0">
               <children>
                  <Button fx:id="yesButton" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" onAction="#yesButtonClicked" text="Yes" textAlignment="CENTER">
                     <HBox.margin>
                        <Insets />
                     </HBox.margin>
                  </Button>
                  <Button fx:id="noButton" alignment="CENTER" contentDisplay="CENTER" layoutX="10.0" layoutY="10.0" mnemonicParsing="false" onAction="#noButtonClicked" text="No" textAlignment="CENTER">
                     <HBox.margin>
                        <Insets />
                     </HBox.margin>
                  </Button>
               </children>
               <VBox.margin>
                  <Insets />
               </VBox.margin>
            </HBox>
         </children>
         <padding>
            <Insets bottom="50.0" top="30.0" />
         </padding>
      </VBox>
   </children>
</AnchorPane>

AlertEmptyNameController. java - это контроллер для представления, когда поле имени пусто и вы нажимаете кнопку добавления человека


package AddressBook;

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

import java.io.IOException;

public class AlertEmptyNameController {

    @FXML
        private Button okButton;
        @FXML
        private Label emptyNameLabel;
        private Stage alertEmptyNamestage;
        private Model model;
        private AlertEmptyNameController alertEmptyNameController;

    public AlertEmptyNameController() {

        System.out.println("+1 AlertEmptyNameControlle() object instantiated");
    }

        public AlertEmptyNameController(Model model){

            this.model = model;
            System.out.println("+1 AlertEmptyNameController(model) object instantiated");
        }

        public void alertEmptyName() throws IOException {

            FXMLLoader alertEmptyNameLoader = new FXMLLoader(getClass().getResource("AlertEmptyNameView.fxml"));
            alertEmptyNameLoader.load();
            AlertEmptyNameController alertEmptyNameController = alertEmptyNameLoader.getController();
            Parent root = alertEmptyNameLoader.getRoot();
            alertEmptyNamestage = new Stage();
            alertEmptyNamestage.setScene(new Scene(root));
            alertEmptyNamestage.setTitle("The Namefield is empty!");
            alertEmptyNamestage.initModality(Modality.APPLICATION_MODAL);
            alertEmptyNamestage.showAndWait();
        }

        @FXML
        public boolean okButtonClicked(ActionEvent actionEvent) {
            boolean answer = true;
            alertEmptyNamestage = (Stage) okButton.getScene().getWindow();
            alertEmptyNamestage.close();
            return answer;
        }
}

AlertEmptyNameView. f xml - т он просматривает AlertEmptyName

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

<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<?import javafx.geometry.Insets?>
<AnchorPane prefHeight="250.0" prefWidth="450.0" stylesheets="@MyStyle.css" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="AddressBook.AlertEmptyNameController">
    <children>
        <VBox fx:id="vBox" alignment="CENTER" spacing="20.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
            <children>
                <Label fx:id="emptyNameLabel" text="The Namefield cannot be empty!" textAlignment="CENTER" />
                <HBox fx:id="hBox" alignment="CENTER" spacing="10.0">
                    <children>
                        <Button fx:id="okButton" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" onAction="#okButtonClicked" text="Ok" textAlignment="CENTER">
                            <HBox.margin>
                                <Insets />
                            </HBox.margin>
                        </Button>
                    </children>
                    <VBox.margin>
                        <Insets />
                    </VBox.margin>
                </HBox>
            </children>
            <padding>
                <Insets bottom="50.0" top="30.0" />
            </padding>
        </VBox>
    </children>
</AnchorPane>

А это, например, NullPointerException, когда я хочу закрыть окно:

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at AddressBook.MainController.closeWindow(MainController.java:163)
    at AddressBook.MainController.lambda$initialize$8(MainController.java:137)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at com.sun.javafx.stage.WindowPeerListener.closing(WindowPeerListener.java:88)
    at com.sun.javafx.tk.quantum.GlassWindowEventHandler.run(GlassWindowEventHandler.java:122)
    at com.sun.javafx.tk.quantum.GlassWindowEventHandler.run(GlassWindowEventHandler.java:40)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassWindowEventHandler.lambda$handleWindowEvent$3(GlassWindowEventHandler.java:151)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:410)
    at com.sun.javafx.tk.quantum.GlassWindowEventHandler.handleWindowEvent(GlassWindowEventHandler.java:149)
    at com.sun.glass.ui.Window.handleWindowEvent(Window.java:1273)
    at com.sun.glass.ui.Window.notifyClose(Window.java:1177)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$4(WinApplication.java:186)
    at java.lang.Thread.run(Thread.java:748)

Я надеюсь, что кто-то может мне помочь.

Cheers


Теперь я удалил метод display () в verifyDialogBoxController. java и поместил его в mainController. java

...

    public boolean display(String title, String message) throws IOException {

        FXMLLoader confirmViewLoader = new FXMLLoader(getClass().getResource("ConfirmDialogBoxView.fxml"));
        confirmViewLoader.load();
        ConfirmDialogBoxController confirmDialogBoxController = confirmViewLoader.getController();
        confirmDialogBoxController.getLabel().setText(message);
        Parent root = confirmViewLoader.getRoot();
        Stage stage = new Stage();
        stage.setTitle(title);
        stage.setScene(new Scene(root));
        stage.initModality(Modality.APPLICATION_MODAL);
        System.out.println("MessageVariable in DisplayMethod is:"+message);
        stage.showAndWait();

        return answer;
    }

    @FXML
    public void closeWindow(WindowEvent e) throws IOException {


        boolean answer = display("Exiting Window", "Are you sure you want to close the window?");
        if (answer) {

            MiniTest.getPrimaryStage().close();
        }
    }
...

1 Ответ

2 голосов
/ 24 апреля 2020

Ваш confirmDialogBoxController в главном контроллере равен нулю: он никогда не инициализируется. Способ установки этого параметра проблематичен c: ConfirmDialogBoxController инициализируется только при загрузке соответствующего F XML (общего для любой пары F XML -контроллер), но кода для загрузки F XML относится к классу ConfirmDialogBoxController, поэтому вы не можете загрузить F XML, пока не получите экземпляр контроллера.

На самом деле ConfirmDialogBoxController не несет ответственности за отображение пользовательского интерфейса, определенного его F XML. Вы должны переместить метод display() в класс MainController:

public class MainController implements Initializable {

    // Existing code omitted...

    // updated close method:

    @FXML
    public void closeWindow(WindowEvent e) throws IOException {

        boolean answer = display("Exiting Window", "Are you sure you want to close the window?");
        if (answer) {

            MiniTest.getPrimaryStage().close();
        }
    }

    public boolean displayConfirmDialog(String title, String message) throws IOException {

        FXMLLoader confirmViewLoader = new FXMLLoader(getClass().getResource("ConfirmDialogBoxView.fxml"));
        confirmViewLoader.load();
        ConfirmDialogBoxController confirmDialogBoxController = confirmViewLoader.getController();
        confirmDialogBoxController.setConfirmMessage(message);
        Parent root = confirmViewLoader.getRoot();
        Stage stage = new Stage();
        stage.setTitle(title);
        stage.setScene(new Scene(root));
        stage.initModality(Modality.APPLICATION_MODAL);
        System.out.println("MessageVariable in DisplayMethod is:"+message);
        stage.showAndWait();

        // Get the user response (true = Yes button clicked) from controller:
        return confirmDialogBoxController.getResponse() ;
    }

}

, а затем обновить ConfirmDialogBoxController:

public class ConfirmDialogBoxController implements Initializable {

    // existing code omitted...

    // This should not be static, and should be a primitive type:

    // private static Boolean answer ;

    private boolean answer ;

    // this method removed:
    /*
    public boolean display(String title, String message) throws IOException {

        FXMLLoader confirmViewLoader = new FXMLLoader(getClass().getResource("ConfirmDialogBoxView.fxml"));
        confirmViewLoader.load();
        ConfirmDialogBoxController confirmDialogBoxController = confirmViewLoader.getController();
        confirmDialogBoxController.confirmLabel.setText(message);
        Parent root = confirmViewLoader.getRoot();
        Stage stage = new Stage();
        stage.setTitle(title);
        stage.setScene(new Scene(root));
        stage.initModality(Modality.APPLICATION_MODAL);
        System.out.println("MessageVariable in DisplayMethod is:"+message);
        stage.showAndWait();
        return answer;
    }
    */

    // This added for convenience:
    public void setConfirmMessage(String message) {
        confirmLabel.setText(message);
    }

    // This added to return the response (answer):

    public boolean getResponse() {
        return answer ;
    }

    // Note also your event handlers should be void:

    @FXML
    public void yesButtonClicked(ActionEvent actionEvent) {

        answer = true;
        stage = (Stage) yesButton.getScene().getWindow();
        stage.close();
        // return answer;
    }

    @FXML
    public void noButtonClicked(ActionEvent actionEvent) {

        answer = false;
        Stage confirmWindow = (Stage) noButton.getScene().getWindow();
        confirmWindow.close();
        // return answer;
    }

}

Возможно, вы захотите подобный рефакторинг для своего другого диалог.

...