2016-03-17 36 views
0

我试图在JavaFX中实现一个MVC解决方案,就像我以前用swing一样。在我看来,有一些差异。我通常的做法是有一个Starter class来初始化一个viewmodel并将它们传递给带有构造函数的controller。然后,我会给view提供controller的引用,以便它可以注册用于UI处理。然后,我会在controller需要访问的任何GUI元素上使用setActionCommand("xy");setActionCommand(); ist不适用于JavaFX。我也看到了我应该为不同元素使用不同控制器的帖子,如here所示。
我开始实施它,因为我习惯了,我现在卡在无法为按钮分配方法的地步。我的3个按钮是这样的:用一个控制器处理多个JavaFX按钮

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); 

我的控制器看起来是这样的:

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()); 
    } 
} 

哪些呢打印:

[email protected][styleClass=button]'Filter zurücksetzen' 
[email protected][styleClass=button]'Neuer Graph' 
[email protected][styleClass=button]'Graph erweitern' 

我如何能够区分按钮,而无需使用if(event.getSource().toString().equals("[email protected][styleClass=button]'Filter zurücksetzen'"));或财产以后的喜欢?
我也期待在CheckBoxMenuItem上使用它。

编辑:
部分解决它通过解析sender到一个按钮。

@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(); 
     } 
    } 

有没有更通用的方法?因为我不想解析其他事件,这会导致更多的try, catch块。尽管这可能是codereview在这一点的问题..

+0

通常的方法是简单地使用不同的处理程序为每个控制。有没有理由不想这么做? –

+0

我不希望我的应用程序充满'controller'类,但仍然使用'mvc patter',但是如前所述,我还不知道如何在JavaFX中正确执行此操作。 –

+0

那么你不一定要为每一个类都有不同的类,只是使用不同的实例。或者只是使用lambda表达式(请参阅hostz的答案)以尽量减少代码开销(或匿名内部类,尽管这些与lambda表达式相比较是冗长的)。 –

回答

3

JavaFX严重依赖lambdas的使用。在这种情况下是事件处理程序很简单(只有几行代码),而不是由任何其他控件重用,你可以做这样的:

Button reset = new Button("Filter zurücksetzen"); 
reset.setOnAction(event -> System.out.println("Clicked on 'Filter zurücksetzen'")); 

如果同样简单的lambda表达式被重用,你可以定义它separatly和重用:

EventHanlder handler = event -> System.out.println("Clicked on 'Filter zurücksetzen'"); 
Button reset = new Button("Filter zurücksetzen"); 
reset.setOnAction(handler); 

或者,如果你想有他们在你定义控制器,你可以做到这一点也无需控制器来实现EventHandler

public void handleClickOnReset(Event event) { 
    System.out.println("Clicked on 'Filter zurücksetzen'"); 
} 

然后像这样使用它: reset.setOnAction(controller :: handleClickOnReset)

+0

听起来不错,我会试一试:)我会标记它,如果它出现 –

2

通常的方法是对每个控件使用不同的处理程序。通常这是用lambda表达式完成的,就像hotzst的答案一样;如果您更喜欢更传统的方法,您也可以将一个或多个参数添加到独立类中,并使用它的不同实例。

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

然后

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"));