如何确保在按钮上的侦听器之前调用按钮上的 Fxml 方法?
How to ensure Fxml method on button will be called before listener on it?
我有一个 controller
启动了一个名为 file
的新 window :
// MainController.java
Stage primaryStage = new Stage();
FXMLLoader fx = new FXMLLoader(Paths.get("../file.fxml").toUri().toURL());
Scene scene = new Scene(fx.load());
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.centerOnScreen();
FileController control = (FileController ) fx.getController();
control.getValiderBE().setOnAction(event1 -> {
System.out.prinln("here 1");
});
我在 FXML file
中得到了一个按钮 :
// file.fxml, fx:controller="FileController"
<Button fx:id="validerBE" onMouseClicked="#validerClickBE" text="Valider">
</Button>
在其 controller
(FileController
的实例)中我得到:
FileController.java
@FXML
private Button validerBE;
@FXML
void validerClickBE(MouseEvent event) {
System.out.prinln("here 2");
}
public Button getValiderBE() {
return validerBE;
}
打印顺序如下:here 1
=> here 2
。 FileController
中的某些方法甚至没有被调用^^ 就像在 here 1
中调用
中的事件一样
但我会按其他顺序排列,因为新的 window
向列表中添加一个元素,第一个源 controller
应该刷新 TableView
(所以在添加之后操作)
首先,请注意您应该使用 onAction
来处理按钮点击,而不是 onMouseClicked
。这样做的原因是,如果用户导航到按钮并激活它(通常使用 space 栏),或者在没有鼠标的情况下触发按钮(例如使用助记符),onMouseClicked
处理程序不会被调用。
所以你应该
<Button fx:id="validerBE" onAction="#validerClickBE" text="Valider" />
和
@FXML
void validerClickBE(ActionEvent event) {
System.out.prinln("here 2");
}
对于事件的排序:没有通用的方法来控制调用事件处理程序的顺序。有一些特殊情况,您可以在某些特定情况下利用它们,但通常不会指定处理程序调用的顺序。因此,如果您有两个相互依赖的操作,它们应该在同一个处理程序中执行。
无论如何,将 UI 控件暴露在控制器之外通常是一种不好的做法 - 它违反了封装原则,并且会使您的代码更难维护。通常,您应该将数据模型传递给控制器,然后控制器可以调用它需要调用的数据模型上的任何操作。
至少,您可以定义一个字段来表示按下按钮时要执行的操作,并从现有的处理程序中调用它,当然,正确的 MVC 方法更可取:
public class FileController {
private Runnable onValidate = () -> {} ;
public void setOnValidate(Runnable onValidate) {
this.onValidate = onValidate ;
}
@FXML
private void validerClickBE(ActionEvent event) {
// whichever order you need....
onValidate.run();
System.out.println("here 2");
}
}
当然还有
FXMLLoader fx = new FXMLLoader(Paths.get("../file.fxml").toUri().toURL());
Scene scene = new Scene(fx.load());
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.centerOnScreen();
FileController control = (FileController ) fx.getController();
control.setOnValidate(() -> System.out.println("here 1"));
我有一个 controller
启动了一个名为 file
的新 window :
// MainController.java
Stage primaryStage = new Stage();
FXMLLoader fx = new FXMLLoader(Paths.get("../file.fxml").toUri().toURL());
Scene scene = new Scene(fx.load());
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.centerOnScreen();
FileController control = (FileController ) fx.getController();
control.getValiderBE().setOnAction(event1 -> {
System.out.prinln("here 1");
});
我在 FXML file
中得到了一个按钮 :
// file.fxml, fx:controller="FileController"
<Button fx:id="validerBE" onMouseClicked="#validerClickBE" text="Valider">
</Button>
在其 controller
(FileController
的实例)中我得到:
FileController.java
@FXML
private Button validerBE;
@FXML
void validerClickBE(MouseEvent event) {
System.out.prinln("here 2");
}
public Button getValiderBE() {
return validerBE;
}
打印顺序如下:here 1
=> here 2
。 FileController
中的某些方法甚至没有被调用^^ 就像在 here 1
中调用
但我会按其他顺序排列,因为新的 window
向列表中添加一个元素,第一个源 controller
应该刷新 TableView
(所以在添加之后操作)
首先,请注意您应该使用 onAction
来处理按钮点击,而不是 onMouseClicked
。这样做的原因是,如果用户导航到按钮并激活它(通常使用 space 栏),或者在没有鼠标的情况下触发按钮(例如使用助记符),onMouseClicked
处理程序不会被调用。
所以你应该
<Button fx:id="validerBE" onAction="#validerClickBE" text="Valider" />
和
@FXML
void validerClickBE(ActionEvent event) {
System.out.prinln("here 2");
}
对于事件的排序:没有通用的方法来控制调用事件处理程序的顺序。有一些特殊情况,您可以在某些特定情况下利用它们,但通常不会指定处理程序调用的顺序。因此,如果您有两个相互依赖的操作,它们应该在同一个处理程序中执行。
无论如何,将 UI 控件暴露在控制器之外通常是一种不好的做法 - 它违反了封装原则,并且会使您的代码更难维护。通常,您应该将数据模型传递给控制器,然后控制器可以调用它需要调用的数据模型上的任何操作。
至少,您可以定义一个字段来表示按下按钮时要执行的操作,并从现有的处理程序中调用它,当然,正确的 MVC 方法更可取:
public class FileController {
private Runnable onValidate = () -> {} ;
public void setOnValidate(Runnable onValidate) {
this.onValidate = onValidate ;
}
@FXML
private void validerClickBE(ActionEvent event) {
// whichever order you need....
onValidate.run();
System.out.println("here 2");
}
}
当然还有
FXMLLoader fx = new FXMLLoader(Paths.get("../file.fxml").toUri().toURL());
Scene scene = new Scene(fx.load());
primaryStage.setScene(scene);
primaryStage.show();
primaryStage.centerOnScreen();
FileController control = (FileController ) fx.getController();
control.setOnValidate(() -> System.out.println("here 1"));