NOTE

以下共两种解决方案。

  1. 手动操作面板容器和其组件(add, remove等)
// 以contentPanel为底,其上覆盖想要展示的panel内容(切换panel)。
private void showSpecifiedPanel(Panel contentPanel, Panel showPanel) {
    contentPanel.removeAll();
    contentPanel.add(showPanel);
    contentPanel.validate();
    contentPanel.repaint();
}
  1. 直接设置窗口的contentPane属性(推荐)。
// 切换内容面板
public void changeContentPane(Container contentPane) {
    this.setContentPane(contentPane);
    this.revalidate();
}

后期如果有其他解决方案,我会继续追加。

需求

在Java GUI编程中,要求点击菜单栏中不同的菜单项,切换主面板中的显示内容。
解决:
主面板为Panel contentPanel(用于放置其他具体的功能面板)。
其他面板,如Panel p1, p2,先自定义好(这些功能面板,向contentPanel面板上添加)。
当点击被监听器监听着的菜单项后,执行以下方法:

// 以contentPanel为底,其上覆盖想要展示的panel内容(切换panel)。
private void showSpecifiedPanel(Panel contentPanel, Panel showPanel) {
    contentPanel.removeAll();
    contentPanel.add(showPanel);
    contentPanel.validate();
    contentPanel.repaint();
}

即:先移除contentPanel上的所有组件,然后放置所需的、具体的某个功能面板。
然后执行validate()repaint()方法,重新绘制图形。

  • 其他相关API
    在处理多Panel切换的过程中,检索到的其他相关API如下:
    hide() 隐藏面板
    show() 显示面板
    isVisible() 面板是否可见
    setVisible(boolean isVisible) 设置面板的可见性
    一开始的解决思路是重叠添加多个面板,然后控制各个面板的可见状态(显示,隐藏)。奈何不成。所以还是使用之上的方法。

效果图

学生菜单项下有添加查看两个菜单项。
点击添加显示添加学生信息面板。
点击查看显示查看学生信息面板。

  • 主面板
  • 添加学生信息(面板细节自定义)
  • 查看学生面板(细节自定义)

Code

import java.awt.BorderLayout;
import java.awt.Label;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;

public class Test {
    public static void main(String[] args) {
        new MyFrame();
    }
}

class MyFrame extends JFrame implements ActionListener {
    private static final long serialVersionUID = 1L;
    MenuBar menuBar;    // 菜单栏
    Menu student;       // 菜单
    MenuItem add, show; // 菜单项
    Panel contentPanel; // 内容面板,其上用于添加其他待切换的面板

    public MyFrame() {
        // 初始化组件
        menuBar = new MenuBar();
        student = new Menu("学生");
        add = new MenuItem("添加");
        show = new MenuItem("查看");
        contentPanel = new Panel();

        // 菜单项添加事件监听器
        add.addActionListener(this);
        show.addActionListener(this);

        // 设置窗口的菜单栏,菜单和各个菜单项。
        student.add(add);
        student.add(show);
        menuBar.add(student);
        setMenuBar(menuBar);

        // 设置布局为边界布局管理器。将contentPanel添加到窗口中心位置。
        setLayout(new BorderLayout());
        contentPanel.add(new Label("欢迎使用教学管理系统"));    // 欢迎页消息
        add(contentPanel, BorderLayout.CENTER);
        
        // 窗口的其他参数
        setTitle("测试");
        setBounds(300, 50, 400, 300);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();
        if (source == add) {
            showSpecifiedPanel(contentPanel, new MyPanel("请添加学生信息"));
        } else if (source == show) {
            showSpecifiedPanel(contentPanel, new MyPanel("您正在查看学生信息"));
        }
    }

    // 以contentPanel为底,其上覆盖想要展示的panel内容(切换panel)。
    private void showSpecifiedPanel(Panel contentPanel, Panel showPanel) {
        contentPanel.removeAll();
        contentPanel.add(showPanel);
        contentPanel.validate();
        contentPanel.repaint();
    }
    
}

// 简易地获取所需的面板(使用时需自定义)
class MyPanel extends Panel {
    public MyPanel(String msg) {
        this.add(new Label(msg));
    }
}

方案2

JFrame类的实例方法:

setContentPane(Container contentPane)revalidate()

封装方法:

// 切换内容面板
public void changeContentPane(Container contentPane) {
    this.setContentPane(contentPane);
    this.revalidate();
}

运行效果相同。都是点击不同的菜单项后,切换不同的主面板。

代码(将以上源码稍作修改即可):

import java.awt.Container;
import java.awt.Label;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;

public class Test {
    public static void main(String[] args) {
        new MyFrame();
    }
}

class MyFrame extends JFrame implements ActionListener {
    private static final long serialVersionUID = 1L;
    MenuBar menuBar;    // 菜单栏
    Menu student;       // 菜单
    MenuItem add, show; // 菜单项
    Panel contentPanel; // 内容面板,其上用于添加其他待切换的面板

    public MyFrame() {
        // 初始化组件
        menuBar = new MenuBar();
        student = new Menu("学生");
        add = new MenuItem("添加");
        show = new MenuItem("查看");
        contentPanel = new Panel();

        // 菜单项添加事件监听器
        add.addActionListener(this);
        show.addActionListener(this);

        // 设置窗口的菜单栏,菜单和各个菜单项。
        student.add(add);
        student.add(show);
        menuBar.add(student);
        setMenuBar(menuBar);

        // 设置布局为边界布局管理器。将contentPanel添加到窗口中心位置。
        this.setContentPane(new MyPanel("这是欢迎页 - setContentPane()"));
        
        // 窗口的其他参数
        setTitle("测试");
        setBounds(300, 50, 400, 300);
        setVisible(true);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
    
    @Override
    public void actionPerformed(ActionEvent e) {
        Object source = e.getSource();
        if (source == add) {
            changeContentPane(new MyPanel("添加学生信息 - setContentPane()"));
        } else if (source == show) {
            changeContentPane(new MyPanel("查看学生信息 - setContentPane()"));
        }
    }
    
    // 切换内容面板
    public void changeContentPane(Container contentPane) {
        this.setContentPane(contentPane);
        this.revalidate();
    }

}

// 简易地获取所需的面板(使用时需自定义)
class MyPanel extends Panel {
    public MyPanel(String msg) {
        this.add(new Label(msg));
    }
}