我正在尝试构建一个基于按钮的动态应用程序,这些按钮可以从创建的面板中切换JFrame的主面板(这是我的应用程序的顶级内容)。
问题更多地与设计问题有关,而不是与开发问题有关。我不确定我的设计,但我会尝试解释它。
我有一个代表我的应用程序的JFrame,其中包含一个JTabbedPane(以及其中的倍数Tabs)。每个选项卡都包含一个默认的JPanel,在JPanel中,我正在调用一个控制器来渲染我的View(我正在尝试使用MVC模式)。
但是从所谓的View中,我有按钮必须切换JPanel的内容(JTabbedPane中包含的Jpanel)。而且我正在寻找切换视图的最佳方法,而不会违反OOP的标准规则。
示意:
JFrame
JTabbedPane
JPanel
View1
Button (pointing somehow to View2)
JPanel
View3
Button (pointing somehow to View4)
当我点击视图1中的按钮时,我希望这样:
JFrame
JTabbedPane
JPanel
View2
...
JPanel
View3
Button (pointing somehow to View4)
并且,一旦加载了View 2,如果我通过JTabbedPane转到View3并单击View3.button,我希望有这样的东西:
JFrame
JTabbedPane
JPanel
View2
...
JPanel
View4
...
正如我所说,这更像是一个设计问题。我的“设计”是否足够好,不必为每个组件提供JFrame的引用?我该怎么做?
我希望我的文字中没有那么多错误,英语不是我的母语。此外,我对英语写作技巧的任何更正都是值得欢迎的。
谢谢。
答案 0 :(得分:1)
我会说你的JTabbedPane是对面板感兴趣的类 - 因为它是JTabbedPane会让它的内容切换。
所以我说扩展JTabbedPane到?TabbedPane(其中?代表'My'或项目中的命名约定),并使其扩展ActionListener,如下所示:
public class MyTabbedPane extends JTabbedPane implements ActionListener {
...
public void actionPerformed(ActionEvent aev) {
// replace panels
revalidate();
repaint();
}
}
然后将选项卡式窗格注册为需要的动作侦听器(可能是按钮)。
如果要切换到多个面板,则需要更多代码才能通过该状态。 你可以编写自己的监听器:
public class PanelSwitchActionListener {
public void panelSwitchRequested(...);
}
然后传递Enum表示要切换到哪个面板,或者甚至是panelSwitchRequested()方法的(...)部分中的面板本身。然后在按钮上添加一个Action(Listener),并使它们对已注册的PanelSwitchActionListener(希望是你的JTabbedPane)激活panelSwitchRequested()。
答案 1 :(得分:0)
我试着回到模特身上。该模型将维护一个视图列表和一种方法,在给定视图参考的情况下,它可以返回下一个视图(即model.getNextView(view)
)。
这个模型可以传递给你的控制器(在这里我会说pafau提到的自定义JTabbedPane)可以根据需要构建所有选项卡。这样您就可以将导航机制与视图分离,并将逻辑委托给模型。
答案 2 :(得分:0)
就个人而言,我会重新考虑使用选项卡式窗格和视图之间切换的设计。通常是/或者选择标签窗格。
但是,如果您仍然需要这种方式,请尝试以不同方式考虑您的观点。我认为JPanels实际上是视图。如果将控制器连接到每个视图,并将模型连接到每个控制器,您将能够在它们之间进行切换,而不会在视图或控制器中添加太多逻辑,但仍然可以将视图与模型分离。我把一个粗略的例子放在一起使用CardLayout和Null Object,但其他方面相当简单。当然,所有类都应该重命名为适合您项目的类。
<强> View.java 强>
public class View extends JPanel {
private CardLayout layout;
public View(Controller controller, JComponent... subviews) {
layout = new CardLayout();
setLayout(layout);
for (int index = 0; index < subviews.length; ++index) {
JButton changeButton = new JButton("Change");
changeButton.addActionListener(controller);
subviews[index].add(changeButton);
add(subviews[index], "View" + index);
}
}
public void setSubview(int index) {
layout.show(this, "View" + index);
}
}
<强> NullView.java 强>
public class NullView extends View {
public NullView() {
super(null);
}
@Override
public void setSubview(int index) {
// do nothing
}
}
<强> Controller.java 强>
public class Controller implements ActionListener {
private Model model;
private View view;
public Controller(Model model) {
this.model = model;
this.view = new NullView();
}
public void setView(View view) {
this.view = view;
}
public void actionPerformed(ActionEvent e) {
model.nextIndex();
view.setSubview(model.getCurIndex());
}
}
<强> Model.java 强>
public class Model {
private int nViews;
private int curIndex;
public Model(int nViews) {
if (nViews <= 0) nViews = 1;
this.nViews = nViews;
}
public void nextIndex() {
curIndex = (curIndex + 1) % nViews;
}
public int getCurIndex() {
return curIndex;
}
}
在您的内容窗格中
Controller controller1 = new Controller(new Model(2));
View view1 = new View(controller1, subview1, subview2);
controller1.setView(view1);
Controller controller2 = new Controller(new Model(3));
View view2 = new View(controller2, subview3, subview4, subview5);
controller2.setView(view2);
JTabbedPane tabbedPane = new JTabbedPane();
tabbedPane.addTab("Tab1", view1);
tabbedPane.addTab("Tab2", view2);