项目场景:
这篇博客是我在编写java手写识别项目(一):初识KNN算法和GUI框架搭建这个项目是遇到的一个问题,关于是继承自JFrame还是JPanel,这两个是 Java Swing 库中的两个基本组件,它们在构建图形用户界面(GUI)时扮演重要的角色。以前我也经常搞不清楚到底是用JFrame还是JPanel,最近经过各种学习,我已经对其有一定了解,我将在这篇文章中用比较容易理解的方式为大家讲解。
问题描述
当继承自JFrame,运行后,会出现“adding a window to a container”报错,
这是因为其中Window代表了一个顶级窗口,而Container是可以包含其他组件的对象,不应该将Window添加到Container中,而JFrame刚好继承自Window,JPanel刚好继承自Container,所以会产生报错,我们需要的是一个用于承载和组织UI组件的画板。
简要区别 :
先来一张表格,清晰又直观:😊
特性 | JFrame | JPanel |
---|---|---|
类型 | 顶层容器 | 轻量级容器 |
用途 | 表示应用程序的主窗口 | 在 JFrame 内部组织界面元素 |
窗口装饰 | 有(标题栏、边框、可选菜单栏) | 无 |
常见操作 | 最小化、最大化、关闭 | 用于布局和分组界面元素 |
层次结构 | 通常包含一个或多个 JPanel | 被包含于 JFrame 或其他容器内 |
示例用途 | 定义整个应用程序界面的外观和行为 | 创建界面的特定部分,如控制面板或布局区 |
视觉表现 | 完整的窗口,用户直接与之交互 | 窗口内的一部分,用于组织内容和布局 |
可见性 | 必须显式设置为可见 (setVisible(true) ) | 不单独存在,依赖于被添加到的容器 |
窗口控制 | 可以控制窗口的大小、位置、行为 | 大小和位置由其父容器决定 |
事件处理 | 可以处理窗口级事件(如打开、关闭) | 主要处理组件级事件(如按钮点击) |
自定义性 | 通常不过多自定义,除非创建复杂的应用程序界面 | 高度可自定义,用于创建具有特定布局和样式的面板 |
交互性 | 可以包含交互元素,但通常作为整体结构 | 高度交互,通常包含多个交互组件 |
应用场景 | 单窗口应用、主界面、独立窗口组件 | 控制面板、数据输入区域、复杂布局设计 |
多窗口管理 | 用于创建和管理多个窗口(MDI应用) | 不能独立管理多窗口 |
嵌套 | 不能嵌套在其他 JFrame 或 JPanel 中 | 可以嵌套在其他 JPanel 或 JFrame 中 |
深入源代码:
关于这两个类的区别是很多初学者容易混淆的
首先,我们从最根本的区别入手:在java的IDE-IDEA中分别按住Ctrl
键,点击JFrame
和JPanel
进入两者的源代码就会发现:
可见,他们两个有着根本性的差别,JFrame
继承自父类Frame
,是一个界面,而JPanel
继承自父类JComponent
,是一个组件。这说明了,我们在创建GUI界面的时候,JFrame
是必不可少的,而在JFrame
中可以创建JPanel
来作为组件的组合体和布局管理。
关于JComponent
这里面有很多我我们所常用的容器组件,具体如下:
JComponent
是 Java Swing 包中的一个基类,用于创建图形用户界面组件。它是许多 Swing 组件的基础,并提供了一系列共通的方法和属性。以下是从 JComponent
类派生的一些主要类:
-
基本组件:
JLabel
:用于显示文本和图像的标签。JButton
:按钮,用户可以点击执行操作。JToggleButton
:可以切换状态的按钮。JCheckBox
:复选框,允许用户选择或取消选择选项。JRadioButton
:单选按钮,通常用于一组内的单选。JTextField
:单行文本输入框。JPasswordField
:用于输入密码的文本框,显示的文本被掩码。JTextArea
:多行文本输入区域。JEditorPane
:可以显示不同格式文本(如 HTML)的编辑区域。JTextPane
:类似于JEditorPane
,但提供更复杂的文本编辑功能。
-
容器类:
JPanel
:通用容器,用于组织其他组件。JScrollPane
:为组件提供滚动视图。JSplitPane
:分割两个组件的容器,允许用户调整分割比例。JTabbedPane
:带有选项卡的容器,每个选项卡可以包含不同的组件。JLayeredPane
:允许组件分层放置。JRootPane
:Swing顶级容器的基础。
-
高级组件:
JTable
:显示表格数据的组件。JList
:显示一列可选择的项目。JComboBox
:下拉列表框,允许用户从多个选项中选择一个。JTree
:显示树形结构数据。JSlider
:滑块,允许用户沿定量区间选择值。JProgressBar
:显示任务进度的条形指示器。JSeparator
:用于分隔界面元素的分隔条。
-
特殊用途组件:
JToolTip
:提供悬停提示的组件。JSpinner
:允许用户通过点击箭头选择值的组件。JInternalFrame
:创建 MDI(多文档界面)应用程序中的子窗口。
这些是 JComponent
的一些主要子类。Swing 库包含了丰富的组件集,可以满足多样化的用户界面需求。每个组件都有其特定的用途和配置方式,可以根据需要在 GUI 应用程序中灵活使用。
一个简单的例子
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JLabel;
import java.awt.BorderLayout;
public class SimpleGUI {
public static void main(String[] args) {
// 创建 JFrame 实例
JFrame frame = new JFrame("Simple GUI Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
// 创建 JPanel 实例
JPanel panel = new JPanel();
// 向 JPanel 添加组件
JButton button = new JButton("Click Me");
JLabel label = new JLabel("Hello, World!");
panel.add(button);
panel.add(label);
// 将 JPanel 添加到 JFrame
frame.getContentPane().add(panel, BorderLayout.CENTER);
// 显示窗口
frame.setVisible(true);
}
}
回到手写识别的项目中
经过简要的区分,我们现在回到java手写识别项目(一):初识KNN算法和GUI框架搭建这个项目中。
如果我们的Main
是继承自JFrame
,报错将出现在下面的frame.add(this);
这一行。这代表JFrame
中只能再添加容器,而不能再添加窗口了。