我正在学习 Java,我必须使用 GUI 开发一个应用程序。我已经让应用程序在命令行中运行了,但是 GUI 快把我逼疯了,让我花费了数小时的时间进行头部撞击和研究,但毫无进展。您能否帮助我打好基础工作,以便我可以进一步发展。我想要一个单框架应用程序,可以通过单击按钮在框架之间切换。我创建了一个框架并添加了三个面板 P1-P3。这些被设置为卡片布局(来自我从论坛上读到的内容)。然后我向这些面板添加了额外的面板,并为其设置了颜色和按钮。
'''
public class MyMainForm extends JFrame{
private JPanel P1;
private JPanel P2;
private JPanel P3;
private JButton btnFrame1;
private JButton btnFrame2;
private JButton button1;
private JTextField thisIsPanel3TextField;
private JButton btn2Frame1;
private final JFrame frame = new JFrame("MyMain Frame");
public MyMainForm() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setContentPane(P1);
pack();
setSize(1000,800);
//setLocation(null);
btnFrame1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
P1.setVisible(false);
setContentPane(new MyMainForm().P2);
}
});
btnFrame2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
P2.setVisible(false);
setContentPane(new MyMainForm().P3);
}
});
button1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
P3.setVisible(false);
setContentPane(new MyMainForm().P2);
}
});
btn2Frame1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
P1.setVisible(false);
setContentPane(new MyMainForm().P3);
}
});
}
public static void main(String[] args) {
MyMainForm MyMainForm = new MyMainForm();
MyMainForm.setVisible(true);
}
}
''' 我可以使用上面的新代码示例显示 P2 或 P3。当我尝试从 P2 或 P3 返回 P1 时,内容窗格不显示?我是否需要重新验证内容窗格才能正常工作?我真的需要能够从 P1 转到 P2
最简单的方法是使用
CardLayout
。只需按照这个例子:
JFrame frame = new JFrame();
JPanel p1 = new JPanel();
p1.setBackground(Color.RED);
JPanel p2 = new JPanel();
p2.setBackground(Color.WHITE);
JPanel p3 = new JPanel();
p3.setBackground(Color.BLUE);
//Create the panel that contains the "cards".
JPanel cards = new JPanel(new CardLayout());
cards.add(p1, "Panel 1");
cards.add(p2, "Panel 2");
cards.add(p3, "Panel 3");
// Add your card container to the frame
Container pane = frame.getContentPane();
pane.add(cards, BorderLayout.CENTER);
JButton btn = new JButton("Click me!");
btn.addActionListener(new ActionListener() {
@Override
public void actionPerformed (ActionEvent e) {
CardLayout cl = (CardLayout)(cards.getLayout());
cl.next(cards);
}
});
JPanel btnPanel = new JPanel();
btnPanel.add(btn);
pane.add(btnPanel, BorderLayout.SOUTH);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 400);
frame.setVisible(true);
或者,您可以通过调用
cl.show(cards, "Panel X")
切换到特定面板,其中 X 是面板编号。这是因为 swing 参数是我分配给每个“卡片”的名称,并且 show
方法会调用按名称添加到 CardLayout
的面板。对于您的示例,每个按钮都应该有一个侦听器,该侦听器使用此方法来“显示”其分配的面板。
CardLayout
是一个不错的选择,但是在 swing 应用程序中的面板之间切换的更通用/可维护的解决方案是使用 State 设计模式。这将允许您将一个 JFrame 作为“上下文”,并且可以通过在各种“状态”实现之间切换来配置不同的面板。结果是使用各种状态对整个应用程序进行更通用的控制,此外,您最终将获得更清晰的代码和关注点分离。
这是一个使用可以具有不同状态的仪表板的简单示例:
首先,我们将创建一个 Dashboard 类,它作为我们的主应用程序,其中包含单击按钮时要更改的框架/面板。
Dashboard.java
public class Dashboard {
private JFrame mainFrame;
private JPanel mainPanel;
private JButton changeStateButton("Click me");
// Initialize the DashboardState as NullState to avoid NPE
private DashboardState state = new NullDashboardState();
public Dashboard() {
// Configure all your buttons to change state to the desired state
changeStateButton.addActionListener(event -> {
changeState(new ExampleDashboardState(this)));
});
}
private void changeState(DashboardState state) {
this.state.clear();
this.state = state;
this.state.render();
}
// Use these accessors to make modifications from the state class
public JFrame getMainFrame() {
return mainFrame;
}
public JPanel getMainPanel() {
return mainPanel;
}
}
接下来,定义一个简单的 State 接口。
DashboardState.java
public interface DashboardState {
// Render the dashboard state
void render();
// Clear the dashboard state to make room for the next state
void clear();
}
接下来,定义
DashboardState
接口的实现。
ExampleDashboardState.java
public class ExampleDashboardState implements DashboardState {
private Dashboard dashboard;
private JPanel dashboardPanel;
public DashboardState(Dashboard dashboard) {
this.dashboard = dashboard;
}
public void render() {
dashboardPanel = dashboard.getMainPanel();
// Do stuff with dashboardPanel
dashboardPanel.revalidate();
dashboardPanel.repaint();
}
public void clear() {
dashboardPanel.removeAll()
// Any other cleanup code runs here
}
}
最后,创建
DashboardState
接口的 Null 实现。
NullDashboardState.java
public class NullDashboardState implements DashboardState {
public void render() {
// Do nothing
}
public void clear() {
// Do nothing
}
}