何时使用 JFrame 或 JPanel

When to use JFrame or JPanel

我是 Java 的 GUI 编程新手,有几个关于何时使用哪些工具的问题。

当我的应用程序是 运行 时,我有一个 JFrame 出现并使用内容面板向用户显示 3 个按钮。我希望每个按钮显示不同的屏幕但不在单独的 window 中打开。为此,我目前正在处理当前的 JFrame 并创建一个包含新内容的新 JFrame。这是我的问题。

  1. 我应该为每次单击按钮创建一个新的 JPanel 而不是创建一个新的 JFrame 吗?如果这个问题的答案见仁见智,是否有普遍接受的最佳做法?

  2. 关闭 JFrame 或 JPanel 时,何时适合使用 setVisible(false) 与 .dispose()?

  1. 您可以使用 CardLayout 切换到完全不同的视图 组件,或者您也可以定义不同的 JPanel(保留或 重新创造将基于他们互动的设计 与或由)和添加和 根据需要从 JFrame 中删除它们。 CardLayout 然而是 为此而设计,所以我建议先研究一下。

    创建新的 JFrame 应该会让用户感到困惑,尤其是当您 不要跟踪框架在他们的显示器上的先前位置或 用户设置的自定义尺寸。我也想象会有一个 之前一帧消失时会发生的闪烁 下一个出现。

  2. 您应该在设置后在 JFrame 上调用 setVisible(true) 它的所有属性,并添加了您需要的所有组件 将添加。正如您在方法中看到的那样,setVisible() 的一部分 文档是它将对齐所有组件,因此如果 你调用它然后添加组件后,你可能只会看到一些 您的组件可见。

    您真的不需要调用 setVisible(false),或者 dispose() 在通常情况下。

我也尽量解释一下。

JFrame - 用于表示 window 应该具有的内容。这包括边框(可调整大小 y/n?)、标题栏(应用程序名称或其他消息)、控件(minimize/maximize 是否允许?)以及各种系统事件的事件处理程序,例如 'window close'(允许应用程序退出了吗?)。

JPanel - 通用 class 用于将其他元素聚集在一起。这对于使用视觉布局或提供的布局管理器之一更为重要,例如gridbaglayout 等。例如,您有一个比您保留的区域大的文本框。将文本框放在滚动窗格中,然后将该窗格放入 JPanel 中。然后当你放置JPanel时,它在布局方面将更易于管理。

切换到其他屏幕后,按钮是否应该留在 JFrame 上?如果是,请为 ContentPane 使用 BorderLayout,并将自己的 JPanel 中的 3 个按钮添加到 BorderLayout.NORTH。为您的自定义屏幕使用 3 个 JPanel,并将它们添加到 BorderLayout.CENTER.

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class ThreeButtonExample extends JFrame {

  private JPanel current;
  private JPanel screen1 = new JPanel();
  private JPanel screen2 = new JPanel();
  private JPanel screen3 = new JPanel();

  public ThreeButtonExample(String title) {
    super(title);
    setMinimumSize(new Dimension(400, 300));

    getContentPane().setLayout(new BorderLayout());

    JPanel buttonPane = new JPanel();

    JButton btnScreen1 = new JButton("Screen 1");
    JButton btnScreen2 = new JButton("Screen 2");
    JButton btnScreen3 = new JButton("Screen 3");

    btnScreen1.setActionCommand("Screen 1");
    btnScreen2.setActionCommand("Screen 2");
    btnScreen3.setActionCommand("Screen 3");

    buttonPane.add(btnScreen1);
    buttonPane.add(btnScreen2);
    buttonPane.add(btnScreen3);

    screen1.setBackground(Color.red);
    screen2.setBackground(Color.green);
    screen3.setBackground(Color.blue);

    btnScreen1.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        changePanel(e);
      }
    });

    btnScreen2.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        changePanel(e);
      }
    });

    btnScreen3.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        changePanel(e);
      }
    });

    getContentPane().add(buttonPane, BorderLayout.NORTH);
    current = screen1;
    getContentPane().add(screen1, BorderLayout.CENTER);

    this.setDefaultCloseOperation(EXIT_ON_CLOSE);
  }

  public void changePanel(ActionEvent e) {
    getContentPane().remove(current);
    switch (e.getActionCommand()) {
      case "Screen 1":
        getContentPane().add(screen1, BorderLayout.CENTER);
        current = screen1;
        break;
      case "Screen 2":
        getContentPane().add(screen2, BorderLayout.CENTER);
        current = screen2;
        break;
      case "Screen 3":
        getContentPane().add(screen3, BorderLayout.CENTER);
        current = screen3;
        break;
    }
    this.revalidate();
    this.repaint();
  }

  public static void main(String[] args) {
    ThreeButtonExample tbe = new ThreeButtonExample("3 Button Test");
    tbe.pack();
    tbe.setVisible(true);
  }

}