ttarczynski
ttarczynski

Reputation: 1014

Pass EventHandler from Controller to View trough method DI - JavaFX

I've been trying to build a simple GUI with JavaFX (I'm completely new to JavaFX) and I've found myself stuck. In every tutorial I've found event handling is done on the level of the UI object, mostly with annonymous inner classes - what I want to accomplish is to move the event handlers to controller class, and inject references to them trough methods called on controller's (and view's) instantiation.

My small GUI is properly build and displayed, the reference is indeed passed, but for a reason the handle() method is not invoked, and I can't find the reason why.

The View:

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

}

The Controller:

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

    }
}

PS I've no such problem while build the GUI with Swing so the issue is connected with JavaFX.

Upvotes: 0

Views: 1059

Answers (1)

Uluk Biy
Uluk Biy

Reputation: 49185

I have tested your code by manual instantiation as:

Controller controller = new Controller( this );

in View.start() method. The event handlers are working as expected with only small problem. Both in addFileMenuListeners() and addStorehouseMenuListeners() methods you are setting the event handler to the same menuitem fileMenu.getItems().get(0). So calling of these method one after another, second invocation is overriding the setOnAction of the first one.

So change the addStorehouseMenuListeners() to:

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

Upvotes: 2

Related Questions