JavaFX Gridpane搜索返回空节点。

问题描述 投票:0回答:1

我想在这里实现自己的自定义对话框。JavaFX 我想用FXML文件来改变对话框的标题和信息。我的 .fxml 文件中的典型对话框的结构是这样的(我在这个例子中使用了一个错误的对话框)。

<StackPane prefHeight="140.0" prefWidth="290.0" style="-fx-background-color: #333333;" stylesheets="/style.css"
           xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1"
           fx:controller="apps.utils.Dialogs">
    <children>
        <BorderPane>
            <center>
                <GridPane>
                    <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>
                    <children>
                        <Label text="Error msg" textFill="LIGHTGRAY"/>
                        <Text fill="LIGHTGRAY" strokeType="OUTSIDE" strokeWidth="0.0"
                              text="My custom error message here"
                              wrappingWidth="250.0" GridPane.rowIndex="1">
                            <GridPane.margin>
                                <Insets top="10.0"/>
                            </GridPane.margin>
                        </Text>
                        <JFXButton onMouseClicked="#close"
                                   style="-fx-background-color: #da294f; -fx-border-radius: 5; -fx-background-radius: 5;"
                                   text="Retry" textFill="LIGHTGRAY" GridPane.halignment="CENTER" GridPane.rowIndex="2"
                                   GridPane.valignment="BASELINE">
                            <GridPane.margin>
                                <Insets top="20.0"/>
                            </GridPane.margin>
                        </JFXButton>
                    </children>
                </GridPane>
            </center>
            <StackPane.margin>
                <Insets bottom="20.0" left="20.0" right="20.0" top="20.0"/>
            </StackPane.margin>
        </BorderPane>
    </children>
</StackPane>

我用来显示对话框的方法(在我的控制器类中)。

    public static void showDialog(StackPane rootPane, BorderPane rootBorderPane, URL dialogFile, String title, String message) throws IOException {
  rootBorderPane.setEffect(boxBlur);
        FXMLLoader loader = new FXMLLoader(dialogFile);
        loader.setClassLoader(cachingClassLoader);
        StackPane dialog = loader.load();
        ObservableList<Node> components = dialog.getChildren();
        BorderPane pane = (BorderPane) components.get(0);
        GridPane content = (GridPane) pane.getCenter();
        System.out.println("row: " + content.getRowCount() + " col:" + content.getColumnCount()); //prints Row 3, col 1

        Label dialogTitle = (Label) findNodeFromIndex(content, 0, 0);
        dialogTitle.setText(title);
        Text dialogMessage = (Text) findNodeFromIndex(content, 0, 1);
        dialogMessage.setText(message);
        //rest of the code to show dialog...
}

然后我有一个函数来搜索Gridpane,像这样。

   private static Node findNodeFromIndex(GridPane gridPane, int col, int row) {
        for (int i = 0; i < gridPane.getChildren().size(); i++) {
            Node node = gridPane.getChildren().get(i);
            if (GridPane.getRowIndex(node) == row && GridPane.getColumnIndex(node) == col) {
                return node;
            }
        }
        return null;
    }

然后我简单地调用 showDialog() 对话框类型、标题以及自定义标题体文本作为我的参数。

现在我的问题是,我得到一个 NullPointerException 在...上 setText() 方法。我想不通为什么会这样?我怎么才能解决这个问题呢?

java javafx nullpointerexception
1个回答
1
投票

我认为 findNodeFromIndex() 正在返回 null 因为你没有明确地在0列等节点上设置列索引。

像这样手动搜索场景图,根本就不是正确的方法。布局上的任何小改动都会彻底破坏这段代码。相反,只需要在控制器类中定义方法来设置标题和消息。

public class Dialogs {

    @FXML
    private Label titleLabel ;

    @FXML
    private Text messageText ;

    public void setTitle(String title) {
        titleLabel.setText(title);
    }

    public void setMessage(String message) {
        messageText.setText(message);
    }

    // ...
}

并设置 fx:id在FXML中的元素上。

<Label fx:id="titleLabel" text="Error msg" textFill="LIGHTGRAY"/>
<Text fx:id="messageText" fill="LIGHTGRAY" strokeType="OUTSIDE" strokeWidth="0.0"
      text="My custom error message here"
      wrappingWidth="250.0" GridPane.rowIndex="1">

然后你可以直接调用这些方法

public static void showDialog(StackPane rootPane, BorderPane rootBorderPane, URL dialogFile, String title, String message) throws IOException {
    rootBorderPane.setEffect(boxBlur);

    FXMLLoader loader = new FXMLLoader(dialogFile);
    loader.setClassLoader(cachingClassLoader);
    StackPane dialog = loader.load();
    Dialogs controller = loader.getController();
    controller.setTitle(title);
    controller.setMessage(message);
    //rest of the code to show dialog...

}
© www.soinside.com 2019 - 2024. All rights reserved.