代码之家  ›  专栏  ›  技术社区  ›  azro

如何确保按钮上的Fxml方法在侦听器之前被调用?

  •  1
  • azro  · 技术社区  · 6 年前

    我有一个 controller 将启动一个名为 file :

    // 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>
    

    在its中 控制器 (实例 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 . 还有一些方法 文件控制器 甚至不被称为^Like,如果事件在 此处1 呼叫

    但我想换个顺序,因为新的 window 将元素添加到列表中,然后添加第一个源 控制器 应刷新 TableView (添加操作后为so)

    1 回复  |  直到 6 年前
        1
  •  2
  •   James_D    6 年前

    首先,请注意,您应该使用 onAction 处理按钮点击,而不是 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"));