当前位置: 首页 > 知识库问答 >
问题:

从 J 面板内部切换 JFrame 中的 J 面板

荀俊迈
2023-03-14

我正在尝试构建一个基于按钮的动态应用程序,这些按钮从创建的面板内部切换JFrame的主面板(这是我的应用程序的顶部内容)。

这个问题更多的是设计问题,而不是开发问题。我不确定我的设计,但我会试着解释一下。

我有一个JFrame代表我的应用程序,其中包含一个JTabbedPane(和多个Tabs)。每个选项卡都包含一个默认的JPanel,在那个JPanel中,我调用一个正在呈现我的视图的控制器(我正在尝试使用MVC模式)。

但是在所谓的视图中,我有一些按钮,它们必须切换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按钮,我希望得到这样的结果:

JFrame
    JTabbedPane
        JPanel
            View2
                ...
        JPanel
            View4
                 ...

正如我所说,这更多的是一个设计问题。我的“设计”是否足够好,不必为每个组件提供JFrame的参考?我如何执行?

我希望我的文章中不要有太多的错误,英语不是我的母语。此外,欢迎对我的英语写作技巧进行任何更正。

谢谢。

共有3个答案

酆茂才
2023-03-14

就我个人而言,我会重新考虑同时使用选项卡式窗格和视图之间切换的设计。通常是首选选项卡式窗格。

然而,如果你仍然需要这样做,试着以不同的方式思考你的观点。我认为JPanel实际上是视图。如果将一个控制器连接到每个视图,将一个模型连接到每个控制器,则可以在它们之间切换,而无需在视图或控制器中放置太多逻辑,但仍然可以将视图与模型解耦。我把一个使用CardLayout和Null对象的粗略示例放在一起,但在其他方面相当简单。当然,所有的类都应该重命名为适合您的项目的名称。

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

}

空视图.java

public class NullView extends View {

    public NullView() {
        super(null);
    }

    @Override
    public void setSubview(int index) {
        // do nothing
    }

}

控制器.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());
    }

}

模型.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);
鲁钱明
2023-03-14

我会尝试回到一个模型上。该模型将维护一个视图列表和一种方法,通过该方法,给定视图引用,它可以返回下一个视图(即 model.getNextView(视图))

这个模型可以被传递到你的控制器(在这里我要说一个自定义的JTabbedPane,正如pafau所提到的),它可以根据需要构建所有的选项卡。这样你就可以将导航机制与视图分离,并将逻辑委托给模型。

李俊雅
2023-03-14

我会说你的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(...);
}

然后传递枚举,指出要切换到哪个面板,或者甚至是面板的 (...) 部分中的面板本身。然后向按钮添加一个操作(侦听器),并使它们针对已注册的面板切换命令()触发面板(希望这将是您的JTabbedPane)。

 类似资料:
  • 我试图在JPanel上画一些简单的形状,但是有一些困难。如果这个问题似乎以前已经回答过,但其他答案似乎没有帮助,请原谅。 我遵循了一个简单的教程,并成功地在JFrame上绘制了一些基本形状,但是当我将代码如何移动到一个扩展JPel的新类中时,屏幕上什么也没有出现。 我尝试过设置首选大小,重新验证和重新绘画。我添加了对super.paint组件的调用,尽管当我直接绘制到JFrame时,这两个调用都不

  • 所以,我试图为一个简单的游戏制作一个基本的功能菜单。我试图通过创建2个JPanels来做到这一点,一个用于实际游戏,另一个用于我的菜单。 我要做的是在我的菜单面板上有一个按钮,当按下这个按钮时,将显示在父JFrame中的JPanel从菜单切换到实际游戏的JPanel。 这是我的密码: 如你所见,我为我的开始按钮创建了一个监听器。在侦听器内部,我使用了一个time循环,通过方法到达JFrame。程序

  • 我在 netbeans 的 GUI 设计器中设计了一个 GV 框架,它有 1 个文本区域、2 个文本框和 1 个 jButtons,它们位于框架的右侧。现在我想在这些组件左侧的 GV 框架中添加一个自定义 JPanel。像这样: http://s25.postimg.org/3lggsdusf/Othe.png 主网格面板(直接构建在班级内部 可以看出,我试图通过 GUI 编辑器通过自动生成的 i

  • 我有一个深灰色的,上面有一个。我将新颜色(0、0、0、5f)设置为标签的背景,并使用按钮多次更改文本。问题是,每次文本更改时,前一个文本仍保留在新文本后面。我将文本从“123456789”改为“1234567”、“12345”和“123”。以下是截图: 我该如何摆脱这个“阴影”?

  • 我现在正在做一个项目,但我找不到解决问题的方法。 这就是我的问题:我有一个JFrame,然后我添加了一个容器JPanel,并向这个容器面板添加了另外两个JPanel,第一个面板(InputPanel)用于用户输入,第二个面板(Board)用于根据用户输入显示指定的算法。 请注意,在我的Board类中,我重写了paintComponent(图形g)来绘制算法。 主框架中的我的代码: 我最初的计划是在

  • 我想使用Prefuse来可视化图表。我按照他们的教程并尝试了他们的示例应用程序。它的源代码可以在这里找到 然而,即使我只是简单地复制完整的代码,生成的图形看起来也不像教程中显示的那样。它只是半可见的,卡在JGroup的左上角。它的某些部分丢失了,因为它们必须显示在面板之外。我尝试了自己的一些图表,但我一直遇到同样的现象。 我认为这不是预期的行为,但我不知道在哪里寻找问题。我不知道这是Swing(x