有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

javajavafx从被调用的阶段传回一个对象

我有两个控制器ClientsViewController正在调用ClientAddWindowController,因此后者创建了一个新阶段。我想做的是,在新阶段中创建一个客户端之后,它将在放置该客户端的ClientsViewController上调用该方法

我的问题是,除了ClientAddWindowController的构造函数外,对ClientsViewController的引用还显示nullpointer异常。我不明白为什么,因为我正在将调用方的引用传递给构造函数。当调用saveClient时,reference显示它是一个空指针。我做错了什么

错误

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at controllers.ClientAddWindowController.saveClient(ClientAddWindowController.java:140)
    at controllers.ClientAddWindowController.lambda$initialize$0(ClientAddWindowController.java:92)

ClientsViewController。java

public class ClientsViewController implements Initializable {

// ...

@FXML private Button addClientButton;

@FXML private ClientAddWindowController clientAddWindowController;

private Client recentlyAddedClient;

@Override
public void initialize(URL location, ResourceBundle resources) {
    addClientButton.setOnAction(event -> {
        openClientAddWindow();
    });
}

public void openClientAddWindow() {
    clientAddWindowController = new ClientAddWindowController(this);
    clientAddWindowController.showStage();
}

public void setRecentlyAddedClient(Client recentlyAddedClient) {
    this.recentlyAddedClient = recentlyAddedClient;
}}

ClientAddWindowController。java

public class  ClientAddWindowController implements Initializable {

// ...

@FXML private Button saveButton;

@FXML private Button cancelButton;

private ClientsViewController clientsViewController;

private Stage clientAddWindowStage;

public ClientAddWindowController() {}

/**
 * Upon creating controller instance, load fxml file and create new stage with scene to be shown. Chosen modality
 * does not allow to do actions other than in this stage.
 * @param clientsViewController is a calling controller
 */
public ClientAddWindowController(ClientsViewController clientsViewController) {
    this.clientsViewController = clientsViewController;
    this.clientAddWindowStage = new Stage();

    FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/client-add-window.fxml"));

    try {
        clientAddWindowStage.setTitle("Dodawanie nowego klienta");
        clientAddWindowStage.initModality(Modality.APPLICATION_MODAL);
        clientAddWindowStage.setScene(new Scene(loader.load()));
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void initialize(URL location, ResourceBundle resources) {
    countryChoiceBox.getItems().addAll(new CountryList().getCountryNames());
    saveButton.setOnAction(event -> saveClient());

}

/**
 * Creates new client with informations based on given fields. After that passes this client to parent controller
 * and closes the Stage.
 */

@FXML
public void saveClient() {

    Client newClient = new Client(
            "test",
            "test",
            "test"
            );
    clientsViewController.setRecentlyAddedClient(newClient);
    clientAddWindowStage.close();
}

/**
 * Show stage provided by creating this controller.
 */
public void showStage() {
    clientAddWindowStage.show();
}}

客户端添加窗口。fxml

    <GridPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="800.0" prefWidth="1280.0" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.ClientAddWindowController">
    <children>
      <TextField fx:id="nameField" GridPane.columnIndex="1" />
      <TextField fx:id="shortNameField" layoutX="330.0" layoutY="34.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
      <TextField fx:id="emailField" GridPane.columnIndex="1" GridPane.rowIndex="2" />
      <TextField fx:id="telephone1Field" GridPane.columnIndex="1" GridPane.rowIndex="3" />
      <TextField fx:id="telephone2Field" GridPane.columnIndex="1" GridPane.rowIndex="4" />
      <TextField fx:id="telephone3Field" GridPane.columnIndex="1" GridPane.rowIndex="5" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="nazwa" GridPane.halignment="CENTER" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="nazwa skrócona" GridPane.rowIndex="1" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="e-mail" GridPane.rowIndex="2" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="telefon" GridPane.rowIndex="3" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="telefon 2" GridPane.rowIndex="4" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="telefon 3" GridPane.rowIndex="5" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="NIP" GridPane.columnIndex="2" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="REGON" GridPane.columnIndex="2" GridPane.rowIndex="1" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="PESEL" GridPane.columnIndex="2" GridPane.rowIndex="2" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="miasto" GridPane.rowIndex="7" />
      <TextField fx:id="nipField" GridPane.columnIndex="3" />
      <TextField fx:id="regonField" GridPane.columnIndex="3" GridPane.rowIndex="1" />
      <TextField fx:id="peselField" GridPane.columnIndex="3" GridPane.rowIndex="2" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="ulica" GridPane.rowIndex="8" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="kod pocztowy" GridPane.rowIndex="9" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="województwo" GridPane.rowIndex="10" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="status klienta" GridPane.columnIndex="2" GridPane.rowIndex="4" />
      <ChoiceBox fx:id="clientStatusChoiceBox" prefHeight="25.0" prefWidth="283.0" GridPane.columnIndex="3" GridPane.rowIndex="4" />
      <TextField fx:id="cityField" GridPane.columnIndex="1" GridPane.rowIndex="7" />
      <TextField fx:id="streetField" GridPane.columnIndex="1" GridPane.rowIndex="8" />
      <TextField fx:id="postalCodeField" GridPane.columnIndex="1" GridPane.rowIndex="9" />
      <ChoiceBox fx:id="voivodeshipChoiceBox" prefHeight="25.0" prefWidth="283.0" GridPane.columnIndex="1" GridPane.rowIndex="10" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="strona www" GridPane.rowIndex="6" />
      <TextField fx:id="urlField" GridPane.columnIndex="1" GridPane.rowIndex="6" />
      <Button fx:id="downloadDataButton" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" prefHeight="25.0" prefWidth="103.0" text="Pobierz dane" GridPane.columnIndex="4" GridPane.halignment="CENTER" />
      <Button fx:id="saveButton" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" onAction="#saveClient" prefHeight="25.0" prefWidth="114.0" text="Zapisz" GridPane.columnIndex="3" GridPane.halignment="CENTER" GridPane.rowIndex="15" />
      <Button fx:id="cancelButton" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" prefHeight="25.0" prefWidth="114.0" text="Anuluj" GridPane.columnIndex="4" GridPane.halignment="CENTER" GridPane.rowIndex="15" />
      <Label alignment="CENTER" contentDisplay="CENTER" prefHeight="17.0" prefWidth="382.0" text="kraj" GridPane.rowIndex="11" />
       <ChoiceBox fx:id="countryChoiceBox" prefHeight="25.0" prefWidth="283.0" GridPane.columnIndex="1" GridPane.rowIndex="11" />
   </children>
</GridPane>

客户端视图。fxml

    <SplitPane dividerPositions="0.7978789769182782" xmlns="http://javafx.com/javafx/8.0.172-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="controllers.ClientsViewController">
    <items>
        <ScrollPane fitToWidth="true" minViewportWidth="480.0" prefHeight="1026.0" prefWidth="790.0">
            <content>
                <TableView fx:id="productsView" minWidth="-Infinity" prefHeight="1007.0" prefWidth="577.0" tableMenuButtonVisible="true">
                    <columns>
                        <TableColumn fx:id="shortNameColumn" editable="false" prefWidth="138.99996948242188" text="skrót" />
                        <TableColumn fx:id="nameColumn" editable="false" prefWidth="71.0" text="nazwa" />
                        <TableColumn fx:id="cityColumn" editable="false" prefWidth="178.0" text="miasto" />
                        <TableColumn fx:id="streetColumn" editable="false" prefWidth="119.0" text="ulica" />
                  <TableColumn fx:id="voivodeshipColumn" prefWidth="75.0" text="województwo" />
                  <TableColumn fx:id="nipColumn" editable="false" prefWidth="75.0" text="nip" />
                  <TableColumn fx:id="emailColumn" prefWidth="75.0" text="e-mail" />
                  <TableColumn fx:id="telephone1Column" editable="false" prefWidth="75.0" text="telefon" />
                  <TableColumn fx:id="statusColumn" editable="false" prefWidth="75.0" text="status" />
                  <TableColumn fx:id="peselColumn" prefWidth="75.0" text="pesel" visible="false" />
                  <TableColumn fx:id="regonColumn" prefWidth="75.0" text="regon" />
                  <TableColumn fx:id="urlColumn" prefWidth="75.0" text="strona www" visible="false" />
                  <TableColumn fx:id="telephone2Column" prefWidth="75.0" text="telefon 2" visible="false" />
                  <TableColumn fx:id="telephone3Column" prefWidth="75.0" text="telefon 3" visible="false" />
                    </columns>
               <columnResizePolicy>
                  <TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
               </columnResizePolicy>
                </TableView>
            </content>
        </ScrollPane>
        <GridPane alignment="CENTER" prefHeight="1009.0" prefWidth="807.0">
            <columnConstraints>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
            </columnConstraints>
            <rowConstraints>
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            </rowConstraints>
         <children>
            <Button fx:id="addClientButton" alignment="CENTER" mnemonicParsing="false" text="Dodaj klienta" GridPane.halignment="CENTER" />
            <Button fx:id="testButton" mnemonicParsing="false" text="Button" GridPane.halignment="CENTER" GridPane.rowIndex="1" />
         </children>
        </GridPane>
    </items>
</SplitPane>

项目结构

project structure img


共 (2) 个答案

  1. # 1 楼答案

    现在请检查两件事: 1.检查FXML文件的位置,例如通过在以下内容之后添加:

    FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/client-add-window.fxml"));
    

    行:

    System.out.println(loader.getLocation());
    

    确保地址正确

    1. 在fxml文件“client add window.fxml”中,在主容器中找到属性fx:controller=“your.controller.location.with.dirs.separated.by.dots”,并确保您拥有它,并且正确设置了控制器位置。如果位置不对,你应该看到红色
  2. # 2 楼答案

    fxml文件中使用的控制器类由JavaFX在视图加载时创建不要自己创建它们因此,您必须稍微重新构造应用程序。我正试图引导你们完成这件事:

    将阶段引用从ClientAddWindowController移动到ClientsViewController。以下是你的ClientsViewController中的重要部分:

    public class ClientsViewController implements Initializable {
        @FXML
        private Button addClientButton;
        private Stage clientAddWindowStage;
    
        @Override
        public void initialize(URL location, ResourceBundle resources) {
            addClientButton.setOnAction(event -> openClientAddWindow());
    
            try {
                clientAddWindowStage = new Stage();
                FXMLLoader loader = new FXMLLoader(getClass().getResource("/client-add-window.fxml"));
                clientAddWindowStage.setTitle("Dodawanie nowego klienta");
                clientAddWindowStage.initModality(Modality.APPLICATION_MODAL);
                clientAddWindowStage.setScene(new Scene(loader.load()));
    
                // get the controller and set this so the other controller can control it
                ClientAddWindowController controller = loader.getController();
                controller.setClientsViewController(this);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public void openClientAddWindow() {
            clientAddWindowStage.show();
        }
    
        public void closeClientAddWindow() {
            clientAddWindowStage.close();
        }
    }
    

    现在ClientAddWindowController的重要部分移除舞台,并为ClientsViewController创建一个setter:

    public class ClientAddWindowController implements Initializable {
        @FXML
        private Button saveButton;
    
        private ClientsViewController clientsViewController;
    
        @Override
        public void initialize(URL location, ResourceBundle resources) {
            saveButton.setOnAction(event -> saveClient());
        }
    
        public void setClientsViewController(ClientsViewController clientsViewController) {
            this.clientsViewController = clientsViewController;
        }
    
        @FXML
        public void saveClient() {
            // ...
            clientsViewController.closeClientAddWindow();
        }
    }
    

    希望这对你有所帮助