模型视图呈现器和复合视图
我试图在 java swing ui 应用程序中遵循 MVP(特别是被动视图)模式。
应用程序的基本设计让人想起向导控件。屏幕分为两个主要部分:
- 活动视图。
- 带有导航按钮的静态导航栏。
用户可以使用按钮来更改活动视图,但该栏始终显示。
对此场景进行建模时,我有一堆不同的筛选器,每个筛选器都有自己的演示者、视图接口和视图实现(使用 JPanel)。然后我有一个 Shell 演示器、视图接口和视图实现,使用 JFrame。这个想法是,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) {
???
}
}
问题出在setActiveView方法中:当View界面是通用的并且因此不知道时,我不确定如何将activeView设置为activePanel关于 JPanel 的任何信息。显然我不希望我的演示者也了解 JPanel。
I'm trying to follow the MVP (specifically Passive-View) pattern in a java swing ui application.
The basic design of the application reminds a wizard control. The screen is divided to two main parts:
- an active view.
- a static navigation bar, with navigation buttons.
The user can use buttons to change the active view, but the bar is always displayed.
Modeling this scenario, I have a bunch of diffirent screers, each with it's own presenter, view interface and view implementation (using JPanel). Then I have a Shell presenter, view intefrace and view implementation, using a JFrame. The idea is that the shell will load first and always by displayed, showing the bottom navigation bar and leaving a space for the active view. The shell presenter will allow setting the current active screen, somewhat like this:
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) {
???
}
}
The problem is in the setActiveView method: I'm not sure how to set the activeView to the activePanel, when the View interface is general and as such doens't know anything about JPanels. Obviously I wouldn't want my presenters to know about JPanels as well.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
可否将View的定义修改为:
这样每个视图都可以轻松获取视图内容? shell 不需要知道返回的 JComponent 的实现是什么。
Could you modify the definition of View to:
So that each view can easily get the view contents? The shell needn't know what implementation of JComponent is being returned.
您的 View 接口需要提供某种方法来获取可在 JPanel 中显示的内容:
然后在 ShellFrame 中(假设您使用 BorderLayout,就像我一样),您可以按以下方式设置视图:
Your View interface needs to provide some way to obtain something displayable in a JPanel:
Then in ShellFrame (assuming you use BorderLayout, as I would) you can set the view in the following way:
问题是您的
JFrame
是View
,而不是每个单独的活动子视图。当前处于活动状态的视图是渲染作业,因此应由View
完成,而不是由Presenter
完成。想象一下,您想要交换另一个View
,该视图不是只有一个子视图可见,而是全部可见,但活动的视图具有不同的背景颜色。演示者仅控制哪一个处于活动状态,而View
则控制活动的含义。因此,如果不破坏封装,您的任务就无法完成,因为您正在尝试做的工作本质上会破坏封装。所以我会做这样的事情:
The problem is that your
JFrame
is theView
, not each individual active sub-view. The view that is active right now is a rendering job, and therefore should be done by theView
, not by thePresenter
. Imagine you wanted to swap in a differentView
that instead of having only one subview visible, they were all visible, but the one that was active had a different background color. The presenter just controls which one is active, but theView
controls what is meant by active.So your task cannot be done without breaking encapsulation because you are trying to do a job that by it's very nature breaks encapsulation. So I would do something like this: