簡體   English   中英

具有多個控制器的JavaFX中的MVC設計

[英]MVC design in JavaFX with multiple controllers

我有一個帶有多個控制器的JavaFX應用程序。 控制器必須相互通信才能操作視圖對象。 根視圖有一個根控制器,還有許多子控制器,每個子控制器都有自己的子視圖。 我的問題是關於此結構的最佳設計。 現在,我已經組織了這樣的事情:

  • RootController引用了每個子控制器。
  • 每個subController都有對其自己的subView對象的引用,並處理該對象的事件;
  • 當對子視圖A中的視圖對象A(可能是按鈕)的操作必須影響子視圖B中的B時,子控制器A包含對ChangeListener A1的引用,該引用是在初始化期間從rootController定義並注入的; ChangeListener調用subController B的方法對viewObject B進行操作; 最終,rootController可以在ChangeListener中對其自己的viewObject進行操作。

我將舉一個例子:

public SubControllerA {
    private Model model;
    //button defined in subView A
    @FXML
    private Button buttonA;
    //Can be an user-defined interface, actually I used ChangeListener from JavaFX
    private ChangeListener listenerA;

    private void setModel(Model model){
        this.model=model;
    }

    private void setListenerA(ChangeListener listener) {
        this.listenerA=listener;
    }

    //method to handle buttonA click
    @FXML
    private void handleButtonAClick(){
        doSomethingOnSubViewA();
        listener.changed();
    }
}


public SubControllerB {
    private Model model;
    //label defined in subView B
    @FXML
    private Label labelB;

    private void setModel(Model model){
        this.model=model;
    }    
    private void doSomethingOnLabelB(){
        label.setText("button A clicked!");
    }
}

public RootController {
    private Model model;
    @FXML
    private BorderPane mainPanel;
    @FXML
    private SubControllerA subControllerA;
    @FXML
    private SubControllerB subControllerB;
    //initialize listeners
    @FXML
    public void initialize() { 
        this.model = new Model();
        subControllerA.setModel(model);
        subControllerB.setModel(model);
        subControllerA.setListenerA(new ChangeListener(){
             public void changed() {
                  doSomethingOnMainPanel();
                  subControllerB.doSomethingOnLabelB();
             }
        }
    } 
}

您認為這是正確的設計嗎? 您有任何改進建議嗎?

謝謝

我正在發布James_D提出的應用於我的示例的解決方案。 這是模型:

public class Model {

    private Observable<Boolean> buttonPressed;

    public Boolean isButtonPressed(){
        return buttonPressed.get();
    }

    public void setButtonPressed(Boolean pressed){
        this.buttonPressed.set(pressed);
    }

    public Observable<Boolean> buttonPressedProperty(){
        return this.buttonPressed;
    }
}

然后SubControllerA:

public SubControllerA {
    private Model model;
    //button defined in subView A
    @FXML
    private Button buttonA;

    public void setModel(Model model){
        this.model=model;
        model.buttonPressedProperty.addListener((observable, oldValue, newValue)->{
            doSomethingOnSubViewA();
        });
    }

    private void doSomethingOnSubViewA() { ... }

    //method to handle buttonA click
    @FXML
    private void handleButtonAClick(){
        model.setButtonPressed(true);
    }
}

子控制器B:

public SubControllerB {
    private Model model;
    //label defined in subView B
    @FXML
    private Label labelB;

    public void setModel(Model model){
        this.model=model;
        model.buttonPressedProperty.addListener((observable, oldValue, newValue)->{
            doSomethingOnLabelB();
        });
    }

    private void doSomethingOnLabelB() { ... }
}

RootController以類似的方式可以偵聽模型更改。 這種模式消除了控制器之間的許多依賴性。 感謝James_D。

我所做的是使MainController擴展TimerTask。 我將子控制器封裝在MainController中。

  1. 每個子控制器都有一個狀態或多個狀態變量,例如枚舉甚至是布爾值。 當MainController調用方法時,每個子控制器都可以構建視圖並處理該視圖中的事件。

  2. 當用戶選擇添加數據或關閉視圖時,子控制器中的狀態變量會更改,並且MainController.run()方法檢測到狀態更改時,MainController會響應該變量的狀態。 它可以告訴MainController從子控制器屬性中提取值,或者可以簡單地告訴MainController不再需要子控制器來維護和響應其視圖。

  3. 然后,MainController允許另一個子控制器通過從MainController調用來構建視圖和/或更新模型數據模型。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM