Представление модели представления и составные представления - PullRequest
7 голосов
/ 11 февраля 2010

Я пытаюсь следовать шаблону MVP (в частности, пассивному просмотру) в приложении java swing ui.

Базовый дизайн приложения напоминает мастера управления. Экран разделен на две основные части:

  • активный вид.
  • статическая панель навигации, с кнопками навигации.

Пользователь может использовать кнопки, чтобы изменить активный вид, но панель всегда отображается.

Моделируя этот сценарий, у меня есть куча разных экранов, каждый со своим презентатором, интерфейсом представления и реализацией представления (с использованием JPanel). Затем у меня есть докладчик Shell, просмотр intefrace и просмотр реализации, используя JFrame. Идея состоит в том, что оболочка будет загружаться первой и всегда отображаться, показывая нижнюю панель навигации и оставляя место для активного просмотра. Спикер оболочки позволит установить текущий активный экран, примерно так:

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) {
        ???
    }
}

Проблема в методе setActiveView: я не уверен, как установить activeView в activePanel, когда интерфейс View является общим и поэтому ничего не знает о JPanels. Очевидно, я бы не хотел, чтобы мои докладчики знали о JPanels.

Ответы [ 3 ]

1 голос
/ 17 февраля 2010

Ваш интерфейс View должен предоставить какой-то способ получить что-то отображаемое в JPanel:

interface View {
    Component getComponent();
}

Затем в ShellFrame (при условии, что вы используете BorderLayout, как я), вы можете установить представление следующим образом:

public setActiveView(View activeView) {
   activePanel.add(activeView.getComponent(), BorderLayout.CENTER);     
}
1 голос
/ 02 августа 2013

Проблема в том, что ваш JFrame равен View, а не каждому отдельному активному подпредставлению. Представление, которое сейчас активно, является заданием рендеринга, и поэтому должно выполняться View, а не Presenter. Представьте, что вы хотите поменять местами View, чтобы вместо того, чтобы было видно только одно подпредставление, все они были видимы, но у того, что было активно, был другой цвет фона. Презентатор просто контролирует, какой из них активен, но View контролирует, что подразумевается под активным.

Так что ваша задача не может быть выполнена без нарушения инкапсуляции, потому что вы пытаетесь выполнить работу, которая по самой своей природе нарушает инкапсуляцию. Поэтому я бы сделал что-то вроде этого:

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;
        }
    }
}
1 голос
/ 11 февраля 2010

Не могли бы вы изменить определение вида:

interface View {
    JComponent getContainer();
}

Чтобы каждое представление могло легко получить содержимое представления? Оболочке не нужно знать, какая реализация JComponent возвращается.

...