我是JavaFX的新手,并尝试创建一个确认对话框。 我已经知道JavaFX中的对话框中没有真正的构建,所以我自己创建了一个这样的:
@FXML
public void delBox() {
try {
Stage dialogStage = new Stage();
AnchorPane root = FXMLLoader.load(getClass().getResource("Dialog.fxml"));
Scene scene = new Scene(root);
dialogStage.setScene(scene);
dialogStage.showAndWait();
} catch(Exception e) {
e.printStackTrace();
}
}
它看起来已经相当不错了,但我不明白的是,这两个阶段如何相互沟通?我想将一个String传递给消息中显示的对话框,当单击对话框窗口中的一个按钮时,我想对此做出相应的反应。
任何人都可以解释一下这两个阶段之间的沟通是如何运作的吗?
顺便说一句:我使用.FXML
文件和控制器类。
答案 0 :(得分:2)
您需要对该对话框的控制器的引用。为此,请创建FXMLLoader
的实例,而不是使用静态FXMLLoader.load(URL)
方法。
例如,假设您有一个班级DialogController
,那么您的Dialog.fxml
就像:
<AnchorPane xmlns:fx="..." fx:controller="DialogController.fxml">
...
</AnchorPane>
然后,您可以使用
访问上面DialogController
方法中的delBox()
Stage dialogStage = new Stage();
FXMLLoader loader = new FXMLLoader(getClass().getResource("Dialog.fxml"));
AnchorPane root = (AnchorPane)loader.load();
DialogController controller = (DialogController) loader.getController();
Scene scene = new Scene(root);
dialogStage.setScene(scene);
dialogStage.showAndWait();
现在你可以在两个控制器之间进行通信。例如,在DialogController
中,您可以定义message
属性,并将其绑定到Label
:
public class DialogController {
private final StringProperty message = new SimpleStringProperty("");
public void setMessage(String message) {
this.message.set(message);
}
public String getMessage() {
return message.get();
}
public StringProperty messageProperty() {
return message ;
}
@FXML
private Label label ;
public void initialize() {
label.textProperty().bind(message);
// ...
}
}
然后返回你的delBox()方法:
//... as before:
AnchorPane root = (AnchorPane)loader.load();
DialogController controller = (DialogController) loader.getController();
controller.setMessage("Hello World");
// ...
类似地,您可以定义在对话框本身中按下控件时设置的属性,并在showAndWait()调用之后观察它们或查询它们。
还有许多其他类似的技巧。一些例子:
https://github.com/james-d/Shared-Data-Controller/tree/master/src
https://github.com/james-d/Dialog-FXML-Example/tree/master/src
https://github.com/james-d/Nested-Controller-Example/tree/master/src/nestedcontrollerexample
答案 1 :(得分:1)
<AnchorPane xmlns:fx="..." fx:controller="DialogController.fxml"> ... </AnchorPane>
FX Controller是一个java文件,因此它必须是 DialogController ,并且应该包含Controller的路径,即
fx:controller="applicationPackageName.DialogController"
上面提到的fxml代码不起作用。它导致了 javafx.fxml.LoadException
的 java.lang.InstantiationException 强>
的 java.lang.NoSuchMethodException 强>
原因:jvm查找具有0个参数的类构造函数来构建实例。为了克服这个错误,需要在java中编码的函数中加载控制器文件:
loader.setController(new ControllerName(""));
总结(工作代码):
FXML文件:
<BorderPane id="background" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="240.0" prefWidth="320.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" >
<bottom>
<HBox alignment="CENTER" prefHeight="100.0" prefWidth="200.0">
<children>
<Button onAction="#close" text="OK" />
</children>
</HBox>
</bottom>
<center>
<Label fx:id="messageLabel" />
</center>
</BorderPane>
控制器文件:
public class PiPreferenceController {
private final String message ;
@FXML
private Label messageLabel ;
@FXML
void initialize() {
messageLabel.setText(message);
}
public PiPreferenceController(String message) {
this.message = message ;
}
@FXML
public void close() {
messageLabel.getScene().getWindow().hide();
}
}
功能:
void dialogPreferences() throws IOException {
Stage dialogStage = new Stage();
FXMLLoader loader = new FXMLLoader(getClass().getResource(
"PiPreference.fxml"));
loader.setController(new PiPreferenceController(""));
BorderPane root = (BorderPane) loader.load();
Scene scene = new Scene(root);
dialogStage.setScene(scene);
dialogStage.showAndWait();
}