Reputation: 1894
I'm trying to implement an MVC solution in JavaFX like I used to with swing. It seems to me that there are some differences. My usual approach was to have a Starter class
to initialize a view
and model
and pass them both to the controller
with the constructor. I would then give the view
a reference to the controller
so it can registrate it for the UI handling. I then would use setActionCommand("xy");
on any GUI element I need to access in the controller
. setActionCommand();
ist not available for JavaFX. I've also seen posts that I should use different controller for different elements, as seen here.
I started implementing it as I'm used to and I'm now stuck at the point where I can't assign a method to a button. My 3 buttons look like this:
Button newGraph = new Button("Neuer Graph");
newGraph.setOnAction(controller);
Button extendGraph = new Button("Graph erweitern");
extendGraph.setOnAction(controller);
Button reset = new Button("Filter zurücksetzen");
reset.setOnAction(controller);
My controller looks like this:
public class GraphController implements EventHandler {
private GraphHandler graphHandler; //model
private GraphView graphView; //view
public GraphController(GraphHandler graphHandler, GraphView graphView, Stage stage){
this.graphHandler = graphHandler;
this.graphView = graphView;
graphView.registerController(this); //introduce controller to view
graphView.start(stage); //start the main frame
}
@Override
public void handle(Event event) {
System.out.println(event.getSource().toString());
}
}
Which does print:
Button@1f74b31a[styleClass=button]'Filter zurücksetzen'
Button@37901011[styleClass=button]'Neuer Graph'
Button@39afc158[styleClass=button]'Graph erweitern'
How can I distinguish the buttons without using if(event.getSource().toString().equals("Button@1f74b31a[styleClass=button]'Filter zurücksetzen'"));
or somthing the like?
I'm also looking forward to use it on CheckBox
and MenuItem
.
Edit:
Partly solved it by parsing the sender
to a button.
@Override
public void handle(Event event) {
try {
Button sender = (Button) event.getSource();
switch (sender.getText()){
case "Filter zurücksetzen":
System.out.println("reset");
break;
case "Neuer Graph":
System.out.println("new");
break;
case "Graph erweitern":
System.out.println("extend");
break;
}
} catch (Exception e){
e.printStackTrace();
}
}
Is there a more generic way? Since I don't want to parse the other events as well, which would result in more try, catch
blocks. Altough this might be a question for codereview
at that point..
Upvotes: 2
Views: 3324
Reputation: 209339
The usual way is to use a different handler for each control. Typically this is done with lambda expressions, as in hotzst's answer; if you prefer a more legacy approach you could also just add one or more parameters to your stand alone class and use different instances of it.
public class ButtonHandler implements EventHandler<ActionEvent> {
private final String message ;
public ButtonHandler(String message) {
this.message = message ;
}
@Override
public handle(ActionEvent event) {
System.out.println(message);
}
}
and then
Button newGraph = new Button("Neuer Graph");
newGraph.setOnAction(new ButtonHandler("New"));
Button extendGraph = new Button("Graph erweitern");
extendGraph.setOnAction(new ButtonHandler("extend"));
Button reset = new Button("Filter zurücksetzen");
reset.setOnAction(new ButtonHandler("reset"));
Upvotes: 3
Reputation: 7496
JavaFX relies heavily on the use of lambdas. In the case were the event handler is simple (only a few lines of code) and not reused by any other controls, you can do it like this:
Button reset = new Button("Filter zurücksetzen");
reset.setOnAction(event -> System.out.println("Clicked on 'Filter zurücksetzen'"));
If the same simple lambda expression is reused you can define it separatly and reuse it:
EventHanlder handler = event -> System.out.println("Clicked on 'Filter zurücksetzen'");
Button reset = new Button("Filter zurücksetzen");
reset.setOnAction(handler);
Or if you want to have them defined in you Controller you can do that as well without the need for the Controller to implement EventHandler
:
public void handleClickOnReset(Event event) {
System.out.println("Clicked on 'Filter zurücksetzen'");
}
And then use it like this: reset.setOnAction(controller::handleClickOnReset)
Upvotes: 4