当前位置: 首页 > 知识库问答 >
问题:

当尝试关闭窗口时,JavaFX NullpointerException在自己的对话框中包含FXML

易昌翰
2023-03-14

我是JavaFX新手。我编写了一个表视图,其中有一个带有地址的人员列表。一切正常。然后我想在MVC或者更好的MVP设计模式中编写它。我正在使用FXML和scenebuilder来布局场景。现在使用MVC时,我遇到的问题是,当我想关闭确认对话框时,我会得到一个NUllpointerException。我也不能更改confirmdialog窗口场景的labeltext。我想我知道问题是什么,但不知道如何妥善解决这个问题。控制器被实例化两次,因此fxml中变量的第一个值为NULL。

所以我是这样写我的小app的:

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中-对于某些事情,比如关闭窗口或删除一个人,我调用类似这样的方法作为我自己的confirmdialogwindow,并将相应的字符串用于标签。

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

            MiniTest.getPrimaryStage().close();
        }

这里是完整的mainController.java-这是mainView(view.fxml)的mainController

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.fxml-这是主视图

<?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”关闭窗口或菜单文件->Exit中的窗口,并用于询问用户是否真的想删除tableview中的条目

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.fxml-这是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>

java-这是当name字段为空并且单击add person时视图的控制器


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.fxml-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)

我希望有人能帮助我。

干杯

我现在删除了ConfirmDialogBoxController.java中的display()方法,并将其放在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个答案

袁安志
2023-03-14

主控制器中的ConfirmDialogBoxController为空:它从未初始化。您的设置方式是有问题的:ConfirmDialogBoxController只有在加载相应的FXML(任何FXML-controller对都通用)时才会初始化,但是加载FXML的代码在ConfirmDialogBoxController类中,因此只有在有了控制器实例之后才能加载FXML。

ConfirmDialogBoxController并不真正负责显示由其FXML定义的UI。您应该将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;
    }

}

您可能希望对其他对话框进行类似的重构。

 类似资料:
  • 场景是:您在窗口(a)中,单击按钮/链接启动打印过程,然后打开一个新窗口(B),其中包含要打印的内容,打印对话立即显示,如果您单击窗口(B)的取消按钮,那么您应该可以再次打印,但当您单击窗口(B)的打印按钮打印时,您可以打印,但窗口(a)的按钮不能再次继续打印。给我一些解决方案…!!!在chrome,Firefox和internet explorer上工作

  • 我想在我的编码中添加对话框。对话框可以弹出。假设用户按下ok按钮后对话框将关闭,但对话框将自动关闭。这是我的密码。有什么问题吗?

  • 本文向大家介绍javascript在当前窗口关闭前检测窗口是否关闭,包括了javascript在当前窗口关闭前检测窗口是否关闭的使用技巧和注意事项,需要的朋友参考一下 在当前窗口关闭前,检测当前窗口是否关闭 在ie9中,如果刷新文档的话,unloadform和onbeforeunload都会执行,如果是关闭页面的话只会执行onbeforeunload事件 值得注意的是,onunload在关闭页面时

  • 我扩展了ControlsFX对话框以创建自定义验证对话框。我添加了一些自定义按钮,其中一个在单击后触发验证操作。如果验证通过,对话框将以OK结果关闭,但如果对话框无效,则会为对话框结果操作分配一个虚拟操作对象。它的目的(dumy result)只是保存用户试图填充对话框的信息,并允许用户进行一些更正(而不是关闭窗口)。一切都会好的,但有一种情况会产生错误的结果。若用户将用错误数据填写表单,则单击验

  • 问题内容: 我目前正在使用窗口处理功能在新窗口中打开地图方向,打开后我将关闭子窗口,该子窗口已打开并在代码中进行重命名工作,但它正在关闭整个浏览器,同时调试了正常工作,但是在运行代码时,出现错误, 错误- 我已经附上了代码, 我做错的地方我不知道。请把我整理一下。 问题答案: 尝试使用此代码关闭新窗口并切换回主窗口