2016-03-17 64 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"));