通过方法DI-JavaFX将EventHandler从控制器传递到视图

通过方法DI-JavaFX将EventHandler从控制器传递到视图,java,model-view-controller,event-handling,javafx-2,Java,Model View Controller,Event Handling,Javafx 2,我一直在尝试用JavaFX构建一个简单的GUI(我对JavaFX完全陌生),但我发现自己陷入了困境。在每一个教程中,我都发现事件处理是在UI对象的级别上完成的,主要是使用无注释的内部类-我想要完成的是将事件处理程序移动到控制器类,并通过在控制器(和视图)实例化时调用的方法向它们注入引用 我的小GUI是正确构建和显示的,引用确实被传递了,但是由于某种原因handle()方法没有被调用,我找不到原因 观点: //imports here public class View extends Appli

我一直在尝试用JavaFX构建一个简单的GUI(我对JavaFX完全陌生),但我发现自己陷入了困境。在每一个教程中,我都发现事件处理是在UI对象的级别上完成的,主要是使用无注释的内部类-我想要完成的是将事件处理程序移动到控制器类,并通过在控制器(和视图)实例化时调用的方法向它们注入引用

我的小GUI是正确构建和显示的,引用确实被传递了,但是由于某种原因handle()方法没有被调用,我找不到原因

观点:

//imports here
public class View extends Application implements ViewInterface, Runnable {
    private Menu fileMenu;
    private Menu storheouseMenu;
    private MenuBar menuBar;
    private Scene scene;
    private MenuItem exitItem;

    public View() {
        initialize();
    }

    public void initialize() {
        fileMenu = new Menu("Plik");
        storheouseMenu = new Menu("Magazyn");
        MenuItem exitItem = new MenuItem("Exit");
        MenuItem displayStorehouse = new MenuItem("Display");
        fileMenu.getItems().addAll(exitItem);
        storheouseMenu.getItems().add(0, displayStorehouse);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        Parent root = new VBox();
        scene = new Scene(root, 400, 200);
        primaryStage.setScene(scene);
        primaryStage.setTitle("Szefowa test");

        menuBar = new MenuBar();
        menuBar.getMenus().addAll(fileMenu, storheouseMenu);
        ((VBox) scene.getRoot()).getChildren().addAll(menuBar);

        primaryStage.setResizable(false);
        primaryStage.show();
    }

    public void addFileMenuListeners(EventHandler<ActionEvent> eventHandler) {
        exitItem = fileMenu.getItems().get(0);
        exitItem.setOnAction(eventHandler);
    }

    public void addStorehouseMenuListeners(EventHandler<ActionEvent> eventHandler) {
        MenuItem displayStorehouse = fileMenu.getItems().get(0);
        displayStorehouse.setOnAction(eventHandler);
    }

    public void displayMessage(String message) {
        Alert alert = new Alert(Alert.AlertType.INFORMATION);
        alert.setTitle("Ping");
        alert.setContentText(message);
    }
//other methods here

}
//此处导入
公共类视图扩展应用程序实现ViewInterface,可运行{
私有菜单文件菜单;
私有菜单存储库菜单;
私人菜单栏菜单栏;
私密场景;
私有货币存在;
公众观点(){
初始化();
}
公共无效初始化(){
fileMenu=新菜单(“Plik”);
storheouseMenu=新菜单(“Magazyn”);
MenuItem EXITETEM=新MenuItem(“退出”);
MenuItem DisplayStore=新MenuItem(“显示”);
fileMenu.getItems().addAll(exitItem);
storheouseMenu.getItems().add(0,显示仓库);
}
@凌驾
public void start(Stage primaryStage)引发异常{
父根=新的VBox();
场景=新场景(根,400200);
初级阶段。场景(场景);
初级阶段设置标题(“Szefowa测试”);
菜单栏=新菜单栏();
menuBar.getMenus().addAll(文件菜单、存储菜单);
((VBox)scene.getRoot()).getChildren().addAll(菜单栏);
primaryStage.SetResizeable(假);
primaryStage.show();
}
public void addFileMenuListeners(EventHandler EventHandler){
exitItem=fileMenu.getItems().get(0);
exitItem.setOnAction(eventHandler);
}
public void addStoreryMenuListeners(EventHandler EventHandler){
MenuItem DisplayStore=fileMenu.getItems().get(0);
DisplayWarehouse.setOnAction(eventHandler);
}
公共无效显示消息(字符串消息){
Alert Alert=新警报(Alert.AlertType.INFORMATION);
警报。设置标题(“Ping”);
alert.setContentText(消息);
}
//这里还有其他方法
}
控制员:

package kitke.szefowa.controller;

//imports here

public class Controller implements ControllerInterface {
    private Model model;
    private View view;

    public Controller(Model model, View view) {
        this.model = model;
        this.view = view;
        this.view.addFileMenuListeners(new FileMenuListener());
        this.view.addStorehouseMenuListeners(new StorehouseMenuListener());
    }


    public class FileMenuListener implements EventHandler<ActionEvent> {

        @Override
        public void handle(ActionEvent event) {
                       //do some stuff
        }
    }

    public class StorehouseMenuListener implements EventHandler<ActionEvent> {

        @Override
        public void handle(ActionEvent event) {
            //do some stuff
            }
        }

    }
}
包kitke.szefowa.controller;
//这里进口
公共类控制器实现ControllerInterface{
私有模型;
私人视野;
公共控制器(模型、视图){
this.model=模型;
this.view=视图;
this.view.addFileMenuListeners(新的FileMenuListener());
this.view.addStorearyMenuListeners(新的StorearyMenuListener());
}
公共类FileMenuListener实现EventHandler{
@凌驾
公共无效句柄(ActionEvent事件){
//做点什么
}
}
公共类仓库MenuListener实现EventHandler{
@凌驾
公共无效句柄(ActionEvent事件){
//做点什么
}
}
}
}

PS我在使用Swing构建GUI时没有此类问题,因此问题与JavaFX有关。

我已经通过手动实例化测试了您的代码,如下所示:

Controller controller = new Controller( this );
View.start()方法中。事件处理程序正在按预期工作,但问题很小。在addFileMenuListeners()和AddStorearyMenuListeners()方法中,您都将事件处理程序设置为相同的menuitem
fileMenu.getItems().get(0)
。因此,一个接一个地调用这些方法,第二次调用将覆盖第一次调用的setOnAction

因此,将AddStoreureMenuListeners()更改为:

public void addstores menulisteners(EventHandler EventHandler)
{
MenuItem DisplayStore=storheouseMenu.getItems().get(0);
DisplayWarehouse.setOnAction(eventHandler);
}

当您实例化控制器类时?我正在使用Spring main DI容器实例化并连接所有对象。但当我尝试手动执行此操作时,同样的情况也会发生。我尝试的顺序如下:1模型2视图3控制器(模型,控制器)这确实有效,但我试图做的是避免在视图中实例化控制器。视图应仅通过对通过refenrece传递的EventHandler类的引用链接到控制器。我有一个主类,我在其中表示模型和视图对象,并将对它们的引用传递给controllers Constructor,后者反过来调用将EventHandler传递给视图的方法。因此,控制器是唯一知道另外两个存在的对象。@Kitke,这只是为了表明eventhandler部分工作正常。若主类中的控制器类的实例化与应答中的类似,那个么它应该可以工作。不幸的是,根据问题中的代码,没什么好说的。是的,谢谢你的回答:-)在我的主类中,实例化看起来非常相似,但它不起作用。。。public static void main(){Model Model=new Model();View View View=new View();Controller Controller=new Controller(Model,View);View.launch(View.class,args);}@Kitke你是从Swing调用这个JavaFX应用程序吗?@uk Bly:不,我根本没有使用Swing。
public void addStorehouseMenuListeners( EventHandler<ActionEvent> eventHandler )
{
    MenuItem displayStorehouse = storheouseMenu.getItems().get(0);
    displayStorehouse.setOnAction( eventHandler );
}