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

时间:2018-02-16 17:28:39

标签: java events button javafx javafx-8

我有一个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>

controllerFileController的实例)中,我得到了:

FileController.java
@FXML
private Button validerBE;
@FXML
void validerClickBE(MouseEvent event) {
   System.out.prinln("here 2");
}
public Button getValiderBE() {
    return validerBE;
}

按顺序打印:here 1 =&gt; here 2FileController中的sometines方法甚至没有被调用^^就像在here 1调用中事件失败一样

但我要按其他顺序排序,因为新的window会在列表中添加一个元素,而第一个来源controller应该刷新TableView(因此添加后)操作)

1 个答案:

答案 0 :(得分:2)

首先,请注意您应该使用onAction来处理按钮点击,而不是onMouseClicked。这样做的原因是,如果用户导航到按钮并激活它(通常使用空格键),或者在没有鼠标的情况下触发按钮(例如,使用助记符),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"));