Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 模型视图演示器和复合视图_Java_Design Patterns_Swing_Mvp_Passive View - Fatal编程技术网

Java 模型视图演示器和复合视图

Java 模型视图演示器和复合视图,java,design-patterns,swing,mvp,passive-view,Java,Design Patterns,Swing,Mvp,Passive View,我试图在JavaSwingUI应用程序中遵循MVP(特别是被动视图)模式 应用程序的基本设计是一个向导控件。屏幕分为两个主要部分: 活动视图 带有导航按钮的静态导航栏 用户可以使用按钮更改活动视图,但始终显示该栏 在对这个场景进行建模时,我有一组不同的screer,每个screer都有自己的演示者、视图接口和视图实现(使用JPanel)。然后,我有一个Shell演示器,使用JFrame查看intefrace和视图实现。其想法是,shell将首先加载,并且始终显示,显示底部导航栏,并为活动视图

我试图在JavaSwingUI应用程序中遵循MVP(特别是被动视图)模式

应用程序的基本设计是一个向导控件。屏幕分为两个主要部分:

  • 活动视图
  • 带有导航按钮的静态导航栏
用户可以使用按钮更改活动视图,但始终显示该栏

在对这个场景进行建模时,我有一组不同的screer,每个screer都有自己的演示者、视图接口和视图实现(使用JPanel)。然后,我有一个Shell演示器,使用JFrame查看intefrace和视图实现。其想法是,shell将首先加载,并且始终显示,显示底部导航栏,并为活动视图留出空间。shell presenter将允许设置当前活动屏幕,有点像这样:

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

问题在于setActiveView方法:我不确定如何将activeView设置为activePanel,因为视图接口是通用的,因此对JPanels一无所知。显然,我不想让我的演示者也知道JPanels。

能否将视图的定义修改为:

interface View {
    JComponent getContainer();
}

以便每个视图都可以轻松获取视图内容?shell不需要知道返回的是JComponent的什么实现。

您的视图界面需要提供某种方式来获取可在JPanel中显示的内容:

interface View {
    Component getComponent();
}
然后在ShellFrame中(假设您像我一样使用BorderLayout),可以按以下方式设置视图:

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

问题是您的
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) {
        ???
    }
}
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;
        }
    }
}
类PresenterManager{
私人演讲者主动演讲者;
所有演讲者的私人名单;
IView视图;
PresenterManager(IView视图){
this.view=视图;
查看。订阅(本);
}
void addPresenter(Presenter p){
所有演示者。添加(p);
}
void setView(int索引){
view.setView(索引);
activePresenter=allPresenters.get(索引);
}
}
类SwingView实现IView{
列出所有视图;
子视图activeView;
int-lastIndex;
公共void集合视图(int索引){
如果(索引!=lastIndex){
activeView.setVisible(false);
activeView=allViews.get(索引);
lastIndex=指数;
}
}
}

你知道怎么做吗?这些答案都不是特别好。我刚刚发布了以下帖子: