Java 在JFrame中从JPanel内部切换JPanel
我试图构建一个基于按钮的动态应用程序,这些按钮从创建的面板内部切换JFrame的主面板(这是我应用程序的顶部内容) 这个问题更多地涉及设计问题,而不是开发问题。我不确定我的设计,但我会尽力解释的 我有一个代表我的应用程序的JFrame,它包含一个JTabbedPane(其中有多个选项卡)。每个选项卡都包含一个默认JPanel,在该JPanel中,我调用一个呈现我的视图的控制器(我尝试使用MVC模式) 但是从所谓的视图来看,我有一些按钮必须切换JPanel的内容(JTabbedPane中包含的JPanel)。我正在寻找切换视图的最佳方式,同时又不违反OOP的标准规则 示意图:Java 在JFrame中从JPanel内部切换JPanel,java,swing,jframe,jpanel,Java,Swing,Jframe,Jpanel,我试图构建一个基于按钮的动态应用程序,这些按钮从创建的面板内部切换JFrame的主面板(这是我应用程序的顶部内容) 这个问题更多地涉及设计问题,而不是开发问题。我不确定我的设计,但我会尽力解释的 我有一个代表我的应用程序的JFrame,它包含一个JTabbedPane(其中有多个选项卡)。每个选项卡都包含一个默认JPanel,在该JPanel中,我调用一个呈现我的视图的控制器(我尝试使用MVC模式) 但是从所谓的视图来看,我有一些按钮必须切换JPanel的内容(JTabbedPane中包含的JP
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)
加载视图2后,如果我通过JTabbedPane进入视图3并单击View3.0按钮,我希望得到如下内容:
JFrame
JTabbedPane
JPanel
View2
...
JPanel
View4
...
正如我所说,这更多的是一个设计问题。我的“设计”是否足够好,不必为每个组件提供JFrame的参考?我该怎么做呢
我希望我的课文中没有那么多错误,英语不是我的母语。此外,欢迎对我的英语写作技巧进行任何修改
谢谢。我想说,您的JTabbedPane是对面板感兴趣的类-因为它是JTabbedPane,可以切换其内容 因此,我建议将JTabbedPane扩展到?TabbedPane(where?代表“我的”或项目中的任何命名约定),并将其扩展为ActionListener,如下所示:
public class MyTabbedPane extends JTabbedPane implements ActionListener {
...
public void actionPerformed(ActionEvent aev) {
// replace panels
revalidate();
repaint();
}
}
然后在需要的地方(可能是按钮)将选项卡式窗格注册为操作侦听器
如果要切换到多个面板,则需要更多代码来传递状态。
您可以编写自己的侦听器:
public class PanelSwitchActionListener {
public void panelSwitchRequested(...);
}
然后在panelswitchrequest()方法的(…)部分传递枚举,指明要切换到哪个面板,甚至可能是面板本身。然后在按钮中添加一个操作(监听器),并使它们对注册的PanelSwitchActionListener(很可能是您的JTabbedPane)触发panelSwitchRequested()。我会尝试使用模型。该模型将维护一个视图列表以及一种方法,通过该列表,给定一个视图引用,它可以返回下一个视图(即
model.getNextView(view)
)
这个模型可以传递给您的控制器(在这里我要说的是pafau提到的定制JTabbedPane),它可以根据需要构造所有选项卡。通过这种方式,您可以将导航机制与视图分离,并将逻辑委托给模型。我个人会重新考虑使用选项卡式窗格和视图之间切换的设计。通常情况下,首选带标签的窗格玻璃 然而,如果你仍然需要这样做,试着用不同的方式思考你的观点。我认为JPanel实际上是观点。如果将控制器附加到每个视图,将模型附加到每个控制器,则可以在它们之间切换,而不会在视图或控制器中添加太多逻辑,但仍然可以将视图与模型分离。我将一个使用和的粗略示例放在一起,但在其他方面相当简单。当然,所有类都应该重命名为适合您的项目的类 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);
}
}
public class NullView extends View {
public NullView() {
super(null);
}
@Override
public void setSubview(int index) {
// do nothing
}
}
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());
}
}
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.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);
}
}
public class NullView extends View {
public NullView() {
super(null);
}
@Override
public void setSubview(int index) {
// do nothing
}
}
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());
}
}
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;
}
}
Model.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);
}
}
public class NullView extends View {
public NullView() {
super(null);
}
@Override
public void setSubview(int index) {
// do nothing
}
}
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());
}
}
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;
}
}
是否需要将视图从View2和View4切换回View1和View3?还是另一种观点?或者你只是在一个方向上切换?是的,也许从视图4我将不得不切换回视图3(从视图2切换到视图1),但它永远不会是选项卡间的切换。+1为了解释好,一定要鼓励。谢谢!我不知道为什么我不考虑听众,这是显而易见的。然而,它给我带来了一个与Java更相关的问题。在我的JTabbedPane中,我没有任何对按钮的引用(按钮将取决于从一个视图到另一个视图),因此我无法在JTabbedPane中添加侦听器。而且,在我看来,我可以添加监听器,但是我没有任何对JTabbedPane的引用,所以我可以将它传递给我自己的监听器。我觉得自己被困在这里了。我看到了一个与我类似的问题:大卫的回答说要给孩子们一个最重要部分的参考。在我的例子中,按照这个方法,我应该给我的控制器一个对JTabbedPane的引用,在控制器中给这个对视图的引用。但是,这在Java(或任何语言)中是一种好的实践吗?这种方法不是违反了MVC的规则吗?也许我错了,因为我只是通过Web框架使用MVC(例如Symfony),但每次我使用它时,控制器都负责视图。此外,通常(在web开发中)有一个控制器和多个视图,而没有任何模型。或控制器,查看并复制与控制器相关的模型,以便对模型执行困难的操作。那么,将视图附加到模型上不是很奇怪吗?M代表模型的右边。控制器将使用模型来控制视图?通过这种方式,您可以在不影响控制器或视图工作方式的情况下更改模型。这就是我的理解anyway@pataprout我不知道MVC是否有任何标准规则。我没有太多时间来分析你的答案,但我想感谢你花了这么多时间,以及你非常精确的答案。我会尽快分析的。