如何在 EventHandler 中使用 FXMLLoader?
How do I use FXMLLoader inside EventHandler?
我正在创建一个 ListView,它能够双击每个项目并有一个 window 弹出窗口,其中包含由 FXML 文件结构化的输入。 FXML 文件 itemStep 包含 fx:controller="controller.ItemStep"
listViewVariable.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {
if (mouseEvent.getClickCount() == 2) {
ItemStep item = listViewVariable.getSelectionModel()
.getSelectedItem();
if (item != null) {
try {
FXMLLoader isLoader = new FXMLLoader(Main.class.getResource("/view/itemStep.fxml"));
AnchorPane pane = isLoader.load();
Scene scene = new Scene(pane);
Stage stage = new Stage();
stage.setScene(scene);
item.setUrl(item.urlField.getText());
stage.show();
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
public void handle(WindowEvent we) {
item.setUrl(item.urlField.getText());
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
});
我继续使用上面的方法得到以下错误。我需要能够在此阶段使用 FXML 文件。
Caused by: java.lang.InstantiationException: controller.ItemStep
at java.lang.Class.newInstance(Unknown Source)
at sun.reflect.misc.ReflectUtil.newInstance(Unknown Source)
... 44 more
Caused by: java.lang.NoSuchMethodException: controller.ItemStep.<init>()
at java.lang.Class.getConstructor0(Unknown Source)
... 46 more
您的 ItemStep
class 没有 no argument constructor。
Does a new instance of ItemStep get recreated after each double[click]?
是的,这就是您编写代码的目的。
如果您不想这样做,您应该在事件处理程序之外调用 FXMLLoader 上的加载方法,将对已加载窗格的引用存储在最终变量中,然后在事件处理程序中使用该引用,而不是每次调用事件处理程序时都加载一个新窗格。
when I invoke both the load FXMLLoader and final AnchorPane outside the event handler I get: AnchorPane@ed39805[styleClass=root]is already set as root of another scene
您不能将一个节点添加到多个场景或不止一次添加到单个场景,您要么必须将其从原始场景中删除,要么只需通过单个实例重新使用原始场景节点。我不知道你想要什么样的行为,但可能你只想有一个 window 弹出窗口并使其成为 modal,而不是每个都创建一个新的 window有人点击某物的时间。
基本上,你会做这样的事情(尽管这只是我从未编译或执行过的大纲,因为我不完全了解你的完整要求,也不知道你的 ItemStep 和 urlField 到底是什么):
final FXMLLoader isLoader = new FXMLLoader(Main.class.getResource("/view/itemStep.fxml"));
final AnchorPane pane = isLoader.load();
final Scene scene = new Scene(pane);
final Stage stage = new Stage();
stage.initModality(Modality.APPLICATION_MODAL);
stage.setScene(scene);
listViewVariable.setOnMouseClicked(event -> {
if (mouseEvent.getButton().equals(MouseButton.PRIMARY) && (mouseEvent.getClickCount() == 2)) {
ItemStep item = listViewVariable.getSelectionModel().getSelectedItem();
if (item != null) {
stage.showAndWait();
item.setUrl(item.urlField.getText());
}
}
});
我正在创建一个 ListView,它能够双击每个项目并有一个 window 弹出窗口,其中包含由 FXML 文件结构化的输入。 FXML 文件 itemStep 包含 fx:controller="controller.ItemStep"
listViewVariable.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
if (mouseEvent.getButton().equals(MouseButton.PRIMARY)) {
if (mouseEvent.getClickCount() == 2) {
ItemStep item = listViewVariable.getSelectionModel()
.getSelectedItem();
if (item != null) {
try {
FXMLLoader isLoader = new FXMLLoader(Main.class.getResource("/view/itemStep.fxml"));
AnchorPane pane = isLoader.load();
Scene scene = new Scene(pane);
Stage stage = new Stage();
stage.setScene(scene);
item.setUrl(item.urlField.getText());
stage.show();
stage.setOnCloseRequest(new EventHandler<WindowEvent>() {
public void handle(WindowEvent we) {
item.setUrl(item.urlField.getText());
}
});
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
});
我继续使用上面的方法得到以下错误。我需要能够在此阶段使用 FXML 文件。
Caused by: java.lang.InstantiationException: controller.ItemStep
at java.lang.Class.newInstance(Unknown Source)
at sun.reflect.misc.ReflectUtil.newInstance(Unknown Source)
... 44 more
Caused by: java.lang.NoSuchMethodException: controller.ItemStep.<init>()
at java.lang.Class.getConstructor0(Unknown Source)
... 46 more
您的 ItemStep
class 没有 no argument constructor。
Does a new instance of ItemStep get recreated after each double[click]?
是的,这就是您编写代码的目的。
如果您不想这样做,您应该在事件处理程序之外调用 FXMLLoader 上的加载方法,将对已加载窗格的引用存储在最终变量中,然后在事件处理程序中使用该引用,而不是每次调用事件处理程序时都加载一个新窗格。
when I invoke both the load FXMLLoader and final AnchorPane outside the event handler I get: AnchorPane@ed39805[styleClass=root]is already set as root of another scene
您不能将一个节点添加到多个场景或不止一次添加到单个场景,您要么必须将其从原始场景中删除,要么只需通过单个实例重新使用原始场景节点。我不知道你想要什么样的行为,但可能你只想有一个 window 弹出窗口并使其成为 modal,而不是每个都创建一个新的 window有人点击某物的时间。
基本上,你会做这样的事情(尽管这只是我从未编译或执行过的大纲,因为我不完全了解你的完整要求,也不知道你的 ItemStep 和 urlField 到底是什么):
final FXMLLoader isLoader = new FXMLLoader(Main.class.getResource("/view/itemStep.fxml"));
final AnchorPane pane = isLoader.load();
final Scene scene = new Scene(pane);
final Stage stage = new Stage();
stage.initModality(Modality.APPLICATION_MODAL);
stage.setScene(scene);
listViewVariable.setOnMouseClicked(event -> {
if (mouseEvent.getButton().equals(MouseButton.PRIMARY) && (mouseEvent.getClickCount() == 2)) {
ItemStep item = listViewVariable.getSelectionModel().getSelectedItem();
if (item != null) {
stage.showAndWait();
item.setUrl(item.urlField.getText());
}
}
});