我想在这里实现自己的自定义对话框。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()
方法。我想不通为什么会这样?我怎么才能解决这个问题呢?
我认为 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...
}