2010-02-10 6 views
7

J'essaie de suivre le modèle MVP (en particulier Passive-View) dans une application java swing ui.Présentation du modèle Présentateur et vues composites

La conception de base de l'application rappelle un contrôle de l'assistant. L'écran est divisé en deux parties principales:

  • une vue active.
  • une barre de navigation statique, avec des boutons de navigation.

L'utilisateur peut utiliser les boutons pour changer la vue active, mais la barre est toujours affichée.

En modélisant ce scénario, j'ai un tas de graveurs diffirent, chacun avec son propre présentateur, l'interface d'affichage et l'implémentation de la vue (en utilisant JPanel). Ensuite, j'ai un présentateur Shell, voir intefrace et voir l'implémentation, en utilisant un JFrame. L'idée est que le shell va charger en premier et toujours en affichant, en affichant la barre de navigation du bas et en laissant un espace pour la vue active. Le présentateur de la coque permettra la mise à l'écran actif actuel, un peu comme ceci:

interface View { 
} 

class Presenter { 
    View view; 

    public Presenter(View view) { 
     this.view = view; 
    } 

    public View getView() { 
     return view; 
    } 

} 

interface ShellView extends View { 
    void setActiveView(View activeView); 
} 

class ShellPresenter extends Presenter { 
    private ShellView shellView; 

    public void setActivePresenter(Presenter activePresenter) { 
     shellView.setActiveView(activePresenter.getView()); 
    } 
} 

class ShellFrame implements ShellView { 
    private JFrame frame; 
    private JPanel activePanel; 
    private JPanel navigationBar; 

    public ShellFrame() { 
     Container c = frame.getContentPane(); 
     c.add(activePanel); 
     c.add(navigationBar); 
    } 

    public setActiveView(View activeView) { 
     ??? 
    } 
} 

Le problème est dans la méthode SetActiveView: Je ne sais pas comment régler le ActiveView au activePanel, lorsque l'interface de visualisation est générale et en tant que tel, ils ne savent rien sur JPanels. Évidemment, je ne voudrais pas que mes présentateurs connaissent aussi JPanels.

+0

Avez-vous déjà trouvé comment faire? Aucune de ces réponses n'est particulièrement bonne. Je viens de poster ce fil: http://stackoverflow.com/questions/17836421/how-dumb-can-mvp-views-really-be – durron597

Répondre

1

Pourriez-vous modifier la définition de vue à:

interface View { 
    JComponent getContainer(); 
} 

Pour que chaque vue peut facilement obtenir le contenu de vue? Le shell n'a pas besoin de savoir quelle implémentation de JComponent est retournée.

1

Votre interface de visualisation doit fournir un moyen d'obtenir quelque chose affichable dans un JPanel:

interface View { 
    Component getComponent(); 
} 

Puis, en ShellFrame (en supposant que vous utilisez BorderLayout, comme je le ferais), vous pouvez définir l'affichage de la manière suivante:

public setActiveView(View activeView) { 
    activePanel.add(activeView.getComponent(), BorderLayout.CENTER);  
} 
1

Le problème est que votre JFrameest le View, et non chaque sous-vue active individuelle. La vue qui est active en ce moment est un travail de rendu, et doit donc être effectuée par le View, et non par le Presenter. Imaginez que vous vouliez échanger dans un autre View qu'au lieu d'avoir une seule sous-vue visible, elles étaient toutes visibles, mais celle qui était active avait une couleur d'arrière-plan différente. Le présentateur contrôle simplement celui qui est actif, mais le View contrôle ce que l'on entend par actif.

Votre tâche ne peut donc pas être accomplie sans casser l'encapsulation, car vous essayez de faire un travail qui, par nature, brise l'encapsulation. Donc, je voudrais faire quelque chose comme ceci:

class PresenterManager { 
    private Presenter activePresenter; 
    private List<Presenter> allPresenters; 

    IView view; 

    PresenterManager(IView view) { 
     this.view = view; 
     view.subscribe(this); 
    } 

    void addPresenter(Presenter p) { 
     allPresenters.add(p); 
    } 

    void setView(int index) { 
     view.setView(index); 
     activePresenter = allPresenters.get(index); 
    } 
} 

class SwingView implements IView { 
    List<SubView> allViews; 
    SubView activeView; 
    int lastIndex; 

    public void setView(int index) { 
     if(index != lastIndex) { 
      activeView.setVisible(false); 
      activeView = allViews.get(index); 
      lastIndex = index; 
     } 
    } 
} 
Questions connexes