GUI图形化演示
概述
Swing组件通常被称为“轻量级组件”,他完全由Java编写,不依赖操作系统语言,他的类继承关系如下:
Java.lang.Object->Java.awt.Component->Java.awt.Container->Javax.swing.JCompoment
JCompoent是swing组件存放的位置,
常用组件如下:
组件名称 | 说明 |
---|---|
JFrame | 框架 |
JDialog | 对话框 |
JOptionPane | 对话框 |
JButton | 按钮 |
JCheckBox | 复选框 |
JComboBox | 下拉框 |
JLabel | 标签 |
JRadioButton | 单选按钮 |
JList | 显示一组条目的组件 |
JTextField | 文本框 |
JPasswordField | 密码框 |
JTextArea | 文本区域 |
继承关系图:
JFrame:
JFrame是一个容器,他是各个组件的载体,在开发过程,我们通过继承java.swing.JFrame来创建给窗体。一般使用BorderLayout布局方式
一.新建JFrame对象:
- new JFrame()创建没有标题的。//也可以直接传一个字符串当作标题
- Frame(String s)创建标题为s的窗口,
二.设置JFrame的大小:
- public void setSize(int width, int height) 设置窗口的大小。
- public void setLocation(int x, int y) 设置窗口的位置,默认位置是 (0, 0) 。
- public void setBounds(int a, int b, int width, int height) 设置窗口的初始位置是 (a, b) ,窗口的宽是 width ,高是 height 。
- public void setVisible(boolean b) 设置窗口是否可见,窗口默认是不可见的。
- public void setResizable(boolean b) 设置窗口是否可调整大小,默认可调整大小。
- public void dispose() 撤销当前窗口,并释放当前窗口所使用的资源。
- public void setExtendedState(int state) 设置窗口的扩展状态,其中参数 state 取 JFrame 类中的下列类常量:
- - MAXIMIZED_HORIZ (水平方向最大化)
- - MAXIMIZED_VERT (垂直方向最大化)
- - MAXIMIZED_BOTH (水平、垂直方向都最大化)
三.设定JFrame的关闭方式
- public void setDefaultCloseOperation(int operation) 该方法用来设置单击窗体右上角的关闭图标后,程序会做出怎样的处理,其中的参数 operation 取 JFrame 类中的下列 int 型 static 常量,程序根据参数 operation 取值做出不同的处理:
- - DO_NOTHING_ON_CLOSE (什么也不做)
- - HIDE_ON_CLOSE (隐藏当前窗口)
- - DISPOSE_ON_CLOSE (隐藏当前窗口,并释放窗体占有的其他资源)
- - EXIT_ON_CLOSE (结束窗口所在的应用程序)
下面来写一下:
package pdsu__zjh;import javax.swing.*;import javax.swing.JFrame;
public class Textt {public static void main(String []args) {JFrame jf=new JFrame();jf.setSize(400,250);//设置长宽jf.setLocation(400,250);//设置位置jf.setVisible(true);//设置是否显示!!!!jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//关闭方式}
}
结果:
布局方式:
setLayout 方法概述
在 Java 的 JFrame
中,setLayout
方法用于设置容器的布局管理器。布局管理器决定了容器中组件的排列方式。JFrame
默认使用 BorderLayout
,但可以通过 setLayout
方法更改为其他布局管理器。
好处:布局方式可以让组件的位置随着窗口的大小而改变。
常用布局管理器
-
BorderLayout(边界布局)
- 将容器分为五个区域:
NORTH
、SOUTH
、EAST
、WEST
和CENTER
。 - 示例代码:
JFrame frame = new JFrame("BorderLayout Example"); // 设置JFrame的布局管理器为BorderLayout,用于管理组件的布局 frame.setLayout(new BorderLayout()); // 创建一个按钮,按钮上的文本为"North",并将其添加到JFrame的NORTH区域 frame.add(new JButton("North"), BorderLayout.NORTH); // 创建一个按钮,按钮上的文本为"South",并将其添加到JFrame的SOUTH区域 frame.add(new JButton("South"), BorderLayout.SOUTH); // 创建一个按钮,按钮上的文本为"East",并将其添加到JFrame的EAST区域 frame.add(new JButton("East"), BorderLayout.EAST); // 创建一个按钮,按钮上的文本为"West",并将其添加到JFrame的WEST区域 frame.add(new JButton("West"), BorderLayout.WEST); // 创建一个按钮,按钮上的文本为"Center",并将其添加到JFrame的CENTER区域 frame.add(new JButton("Center"), BorderLayout.CENTER); // 设置JFrame的大小为宽度300像素,高度200像素 frame.setSize(300, 200); // 设置JFrame的默认关闭操作,当关闭窗口时退出应用程序 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 设置JFrame可见,即显示窗口 frame.setVisible(true);
- 将容器分为五个区域:
-
FlowLayout(流式布局)
- (组件按照添加顺序从左到右排列,当一行排满时自动换行。
- 示例代码:
JFrame frame = new JFrame("FlowLayout Example"); frame.setLayout(new FlowLayout()); frame.add(new JButton("Button 1")); frame.add(new JButton("Button 2")); frame.add(new JButton("Button 3")); frame.setSize(300, 200); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true);
-
GridLayout(网格布局)
- 将容器划分为指定行数和列数的网格,组件按顺序填充网格。
- 示例代码:
JFrame frame = new JFrame("GridLayout Example"); frame.setLayout(new GridLayout(2, 3)); // 2行3列 frame.add(new JButton("Button 1")); frame.add(new JButton("Button 2")); frame.add(new JButton("Button 3")); frame.add(new JButton("Button 4")); frame.add(new JButton("Button 5")); frame.setSize(300, 200); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true);
-
GridBagLayout
- 提供更灵活的布局方式,允许组件跨越多个行和列。
- 示例代码:
JFrame frame = new JFrame("GridBagLayout Example"); frame.setLayout(new GridBagLayout()); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridx = 0; gbc.gridy = 0; frame.add(new JButton("Button 1"), gbc); gbc.gridx = 1; gbc.gridy = 0; frame.add(new JButton("Button 2"), gbc); gbc.gridx = 0; gbc.gridy = 1; gbc.gridwidth = 2; frame.add(new JButton("Button 3"), gbc); frame.setSize(300, 200); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true);
自定义布局
如果默认的布局管理器不满足需求,可以通过实现 LayoutManager
接口来自定义布局。自定义布局需要实现 LayoutManager
接口中的方法,如 addLayoutComponent
、removeLayoutComponent
、layoutContainer
等。
注意事项
- 在设置布局管理器后,添加的组件将按照新的布局管理器进行排列。
- 如果不需要布局管理器,可以将布局管理器设置为
null
,此时需要手动设置组件的位置和大小。
JFrame frame = new JFrame("Null Layout Example");
frame.setLayout(null);
JButton button = new JButton("Button");
button.setBounds(50, 50, 100, 30); // 手动设置位置和大小
frame.add(button);
frame.setSize(300, 200);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
通过 setLayout
方法,可以灵活地控制 JFrame
中组件的排列方式,满足不同的界面设计需求。
面板与布局的嵌套:
我们都知道一个窗口只有一种布局方式,如果想让你的窗口既有流水布局,又有网格布局等,要怎么操作呢?这个时候就要用到面板了,面板是个很小的容器,也是组件可以添加在窗口中。
简单例子:
package pdsu__zjh;import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;public class Textt {public static void main(String[] args) {// 创建一个JFrame窗口JFrame frame = new JFrame();// 设置窗口的位置和大小(x坐标500, y坐标500, 宽度500, 高度400)frame.setBounds(500, 500, 500, 400);// 使窗口可见(注意:应在所有组件添加完成后再调用此方法)frame.setVisible(true);// 创建GridLayout布局管理器(默认2行1列)GridLayout gridLayout = new GridLayout();// 设置布局的行数为2(列数会根据添加的组件数量自动计算)gridLayout.setRows(2);// 将JFrame的布局管理器设置为GridLayoutframe.setLayout(gridLayout);// 创建第一个面板(使用AWT的Panel类)Panel panel1 = new Panel();// 设置面板背景颜色为粉色panel1.setBackground(Color.PINK);// 创建第二个面板(使用AWT的Panel类)Panel panel2 = new Panel();// 设置面板背景颜色为青色panel2.setBackground(Color.CYAN);// 将面板1添加到JFrame中(GridLayout的第一行)frame.add(panel1);// 将面板2添加到JFrame中(GridLayout的第二行)frame.add(panel2);}
}
监听器:
监听器的概念
在Java中,监听器(Listener)是一种设计模式,用于监听特定事件的发生。当事件发生时,监听器会触发相应的处理逻辑。监听器通常用于GUI编程、网络编程等场景,用于处理用户交互、数据变化等事件。
监听器的类型
Java中常见的监听器类型包括:
- ActionListener:用于处理按钮点击等动作事件。
- MouseListener:用于处理鼠标点击、移动等事件。
- KeyListener:用于处理键盘按键事件。
- WindowListener:用于处理窗口事件,如窗口打开、关闭等。
- ItemListener:用于处理复选框、下拉列表等组件的状态变化事件。
监听器的使用步骤
- 实现监听器接口:创建一个类并实现相应的监听器接口,重写接口中的方法。
- 注册监听器:将监听器对象注册到需要监听的组件上。
- 处理事件:在监听器的方法中编写事件处理逻辑。
- 还有一种是使用内部类,将1和2步骤写在一起,用匿名内部类的格式
示例代码
以下是一个使用ActionListener
的简单示例,监听按钮点击事件:
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class ButtonClickListener {public static void main(String[] args) {JFrame frame = new JFrame("Button Click Example");JButton button = new JButton("Click Me");// 创建监听器对象ActionListener listener = new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("Button clicked!");}};// 注册监听器button.addActionListener(listener);frame.add(button);frame.setSize(300, 200);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);}
}
自定义监听器
除了使用Java提供的标准监听器接口,还可以自定义监听器接口和实现类。以下是一个自定义监听器的示例:
// 自定义监听器接口,定义了事件处理方法
interface MyEventListener {// 定义一个方法,用于处理事件,参数message表示事件相关的信息void onEvent(String message);
}// 事件源类,负责触发事件并通知监听器
class EventSource {// 声明一个监听器对象,用于存储注册的监听器private MyEventListener listener;// 设置监听器的方法,将传入的监听器对象赋值给成员变量listenerpublic void setEventListener(MyEventListener listener) {this.listener = listener;}// 触发事件的方法,当调用此方法时会通知已注册的监听器处理事件public void triggerEvent(String message) {// 检查是否有已注册的监听器if (listener != null) {// 如果有监听器,则调用监听器的onEvent方法,并传递事件信息messagelistener.onEvent(message);}}
}// 监听器实现类,实现了MyEventListener接口,处理具体的事件逻辑
class MyEventListenerImpl implements MyEventListener {// 实现接口中的onEvent方法,用于处理接收到的事件@Overridepublic void onEvent(String message) {// 简单地打印出接收到的事件信息System.out.println("Event received: " + message);}
}public class CustomListenerExample {public static void main(String[] args) {// 创建一个事件源对象EventSource source = new EventSource();// 为事件源设置一个监听器,这里创建了一个监听器实现类的实例并传入source.setEventListener(new MyEventListenerImpl());// 触发事件,调用事件源的triggerEvent方法并传递事件信息source.triggerEvent("Hello, Custom Listener!");}
}
使用自定义监听器
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;// 自定义监听器接口
interface MyButtonListener {void onButtonClicked(String message);
}// 自定义JFrame类,包含按钮和监听器注册机制
class MyFrame extends JFrame {private JButton button;private MyButtonListener listener;public MyFrame(String title) {super(title);setSize(300, 200);setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setLayout(new FlowLayout());// 创建按钮button = new JButton("点击我");add(button);// 为按钮添加内置的ActionListenerbutton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {// 当按钮被点击时,触发自定义监听器的事件if (listener != null) {listener.onButtonClicked("按钮被点击了!");}}});}// 注册自定义监听器的方法public void setMyButtonListener(MyButtonListener listener) {this.listener = listener;}
}// 主类:演示如何使用自定义监听器
public class CustomListenerInFrameExample {public static void main(String[] args) {SwingUtilities.invokeLater(() -> {// 创建自定义窗口MyFrame frame = new MyFrame("自定义监听器示例");// 注册自定义监听器frame.setMyButtonListener(new MyButtonListener() {@Overridepublic void onButtonClicked(String message) {// 实现自定义事件处理逻辑JOptionPane.showMessageDialog(frame, message, "事件通知", JOptionPane.INFORMATION_MESSAGE);}});frame.setVisible(true);});}
}
总结
Java中的监听器机制为事件驱动编程提供了强大的支持。通过实现和注册监听器,可以有效地处理各种用户交互和系统事件。无论是使用标准监听器接口还是自定义监听器,都可以根据具体需求灵活地设计和实现事件处理逻辑。
滚动面板和列表
面板:
1. Panel(AWT 组件)
- AWT 组件:属于
java.awt
包,是 AWT 库中最基本的容器组件。 - 重量级:每个
Panel
对应一个原生窗口句柄,依赖底层操作系统绘制。 - 简单功能:主要用于组织和布局其他组件,不支持复杂 UI 特性。
- 有限定制:外观由操作系统决定,难以实现自定义样式(如透明效果)。
- 事件模型:使用 AWT 事件模型,处理方式较繁琐。
核心方法:
add(Component comp)
:添加子组件。setLayout(LayoutManager mgr)
:设置布局管理器。setBackground(Color c)
:设置背景颜色。
示例代码:
java
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;public class PanelExample {public static void main(String[] args) {Frame frame = new Frame("AWT Panel示例");frame.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {System.exit(0);}});// 创建Panel并设置布局Panel panel = new Panel();panel.setLayout(new FlowLayout());// 添加组件到Panelpanel.add(new Button("按钮1"));panel.add(new Button("按钮2"));frame.add(panel);frame.setSize(300, 200);frame.setVisible(true);}
}
2. JPanel(Swing 组件)
特点:
- Swing 组件:属于
javax.swing
包,是 Swing 库中常用的轻量级容器。 - 轻量级:不依赖原生窗口句柄,由 Java 代码绘制,跨平台一致性好。
- 丰富功能:支持双缓冲、透明效果、边框装饰等现代 UI 特性。
- 高度可定制:可自定义外观、添加事件监听器、使用 Swing 提供的各种 UI 组件。
- 事件模型:与 Swing 事件模型集成,处理更简洁(如使用匿名内部类)。
核心方法:
add(Component comp)
:添加子组件。setLayout(LayoutManager mgr)
:设置布局管理器。setOpaque(boolean isOpaque)
:设置是否透明。setBorder(Border border)
:设置边框样式。
示例代码:
java
package pdsu__zjh;import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;public class Textt {public static void main(String[] args) {JFrame frame=new JFrame("Hallow!,World");frame.setBounds(500, 500, 500, 500);frame.setAlwaysOnTop(true);//将窗口置顶ScrollPane scollPane=new ScrollPane();frame.add(scollPane);GridLayout gridLayout=new GridLayout();gridLayout.setRows(20);Panel panel=new Panel();panel.setLayout(gridLayout);for (int i = 0; i < 20; i++) {panel.add(new Button("按钮"+i));}scollPane.add(panel);frame.setVisible(true);}
}
主要区别对比
特性 | JPanel (Swing) | Panel (AWT) |
---|---|---|
包路径 | javax.swing | java.awt |
组件类型 | 轻量级(Java 纯代码实现) | 重量级(依赖原生窗口系统) |
透明效果 | 支持setOpaque(false) | 不支持,始终完全不透明 |
边框装饰 | 支持各种边框(BorderFactory ) | 无内置边框支持 |
双缓冲 | 默认启用,减少闪烁 | 不支持,可能有绘制闪烁问题 |
事件处理 | 更简洁(如匿名内部类) | 较繁琐(需实现接口) |
布局管理器 | 完全支持所有布局管理器 | 支持基本布局,但对复杂布局支持有限 |
推荐场景 | 现代 Java GUI 应用(JFrame、JDialog) | 传统 AWT 应用或简单工具 |
选择建议
-
优先使用 JPanel:
- 如果你的应用是基于 Swing 的。
- 需要透明效果、自定义边框或其他现代 UI 特性。
- 需要更好的跨平台一致性。
-
使用 Panel:
- 在纯 AWT 应用中,或需要与旧代码兼容时。
- 对 UI 要求简单,不需要复杂的视觉效果。
-
注意事项:
- 避免在同一个界面中混用 AWT 和 Swing 组件,可能导致绘制问题和性能下降。
- 使用 Swing 组件时,确保在事件调度线程(EDT)中创建和操作 UI,避免线程安全问题。
常见应用场景
-
JPanel:
- 创建复杂的表单界面(如注册页面)。
- 实现分区域布局(如左侧菜单 + 右侧内容)。
- 作为自定义组件的基类(如游戏面板)。
-
Panel:
- 简单的工具窗口(如计算器)。
- 与 AWT 绘图 API 结合使用(如
Graphics
)。 - 旧 Java 应用的维护和扩展。
2 滚动面板
Swing组件不能使用setDefaultCloseOperation()方法,如果想要关闭就要设置事件
1. JScrollPane(Swing 组件)
特点:
- Swing 组件:属于 Swing 包(
javax.swing
),支持现代 UI 特性(如双缓冲、透明效果)。 - 可定制性强:支持水平和垂直滚动条的精细控制,可自定义滚动条样式、显示策略。
- 事件驱动:与 Swing 事件模型集成,适合复杂交互场景。
- 线程安全:建议在事件调度线程(EDT)中操作,避免 UI 更新冲突。
- 轻量级:不依赖底层窗口系统,跨平台一致性好。
核心方法:
setViewportView(Component view)
:设置需要滚动显示的组件。setHorizontalScrollBarPolicy(int policy)
:设置水平滚动条的显示策略。setVerticalScrollBarPolicy(int policy)
:设置垂直滚动条的显示策略。getHorizontalScrollBar()
/getVerticalScrollBar()
:获取滚动条实例进行定制。
示例代码(修正后的版本):
java
import javax.swing.*;
import java.awt.*;public class JScrollPaneExample {public static void main(String[] args) {SwingUtilities.invokeLater(() -> {JFrame frame = new JFrame("JScrollPane示例");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);// 创建内容面板JPanel contentPanel = new JPanel();contentPanel.setLayout(new GridLayout(20, 1)); // 20行1列for (int i = 0; i < 20; i++) {contentPanel.add(new JButton("按钮" + i));}// 创建JScrollPane并设置内容面板JScrollPane scrollPane = new JScrollPane(contentPanel);scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);frame.add(scrollPane);frame.setSize(400, 300);frame.setVisible(true);});}
}
2. ScrollPane(AWT 组件)
特点:
- AWT 组件:属于 AWT 包(
java.awt
),依赖底层窗口系统绘制。 - 简单直接:功能相对基础,适合简单滚动需求。
- 重量级:每个组件对应一个原生窗口句柄,可能影响性能。
- 有限定制:滚动条样式和行为由操作系统决定,定制性差。
- 兼容性:与 AWT 事件模型集成,在纯 AWT 应用中使用更方便。
核心方法:
add(Component comp)
:添加需要滚动显示的组件(自动处理滚动)。setScrollbarDisplayPolicy(int policy)
:设置滚动条显示策略。getHAdjustable()
/getVAdjustable()
:获取滚动条的调整器(用于手动控制)。
示例代码:
java
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;public class ScrollPaneExample {public static void main(String[] args) {Frame frame = new Frame("ScrollPane示例");frame.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {System.exit(0);}});// 创建AWT ScrollPaneScrollPane scrollPane = new ScrollPane(ScrollPane.SCROLLBARS_ALWAYS);// 创建内容面板Panel contentPanel = new Panel();contentPanel.setLayout(new GridLayout(20, 1));for (int i = 0; i < 20; i++) {contentPanel.add(new Button("按钮" + i)); // AWT Button}// 添加内容到ScrollPanescrollPane.add(contentPanel);frame.add(scrollPane);frame.setSize(400, 300);frame.setVisible(true);}
}
3. 主要区别对比
特性 | JScrollPane (Swing) | ScrollPane (AWT) |
---|---|---|
包路径 | javax.swing | java.awt |
组件类型 | 轻量级(Java 纯代码实现) | 重量级(依赖原生窗口系统) |
添加内容方式 | setViewportView(component) | add(component) |
滚动条定制 | 高度可定制(颜色、样式、策略) | 由操作系统决定,定制性差 |
事件处理 | 与 Swing 事件模型集成 | 与 AWT 事件模型集成 |
线程安全性 | 需要在 EDT 中操作 | 无需特殊处理(但可能有线程问题) |
布局管理器支持 | 支持复杂布局(如嵌套面板) | 简单布局,依赖容器默认布局 |
推荐场景 | 现代 Java GUI 应用(JFrame、JDialog) | 传统 AWT 应用或简单工具 |
4. 选择建议
- 优先使用 JScrollPane:如果你的应用是基于 Swing 的,需要更好的 UI 定制性和跨平台一致性。
- 使用 ScrollPane:在纯 AWT 应用中,或需要与旧代码兼容时。
- 注意事项:避免在同一个界面中混用 AWT 和 Swing 组件,可能导致绘制问题和性能下降。
列表组件:
我只介绍一下AWT中的列表组件:
在 Java AWT(Abstract Window Toolkit)中,列表组件主要提供两种:List
(下拉列表框)和Choice
(单选下拉菜单)。它们都是用户界面中常用的选择组件,但功能和使用场景略有不同。
1. List 组件
java.awt.List
是一个可滚动的多行选择列表,支持单选或多选。
特点:
- 显示多个选项,可通过滚动条浏览。
- 支持单选(默认)或多选(通过
setMultipleMode(true)
启用)。 - 用户可通过鼠标或键盘选择一个或多个项目。
核心方法:
add(String item)
:添加选项。select(int index)
:选择指定索引的选项。getSelectedIndex()
:获取选中项的索引(单选模式)。getSelectedIndexes()
:获取所有选中项的索引(多选模式)。setMultipleMode(boolean b)
:启用 / 禁用多选模式。
示例代码:
java
import java.awt.*;
import java.awt.event.*;public class ListExample {public static void main(String[] args) {Frame frame = new Frame("AWT List 示例");frame.setSize(300, 200);// 创建List组件(默认单选)List list = new List(5); // 显示5行list.add("选项1");list.add("选项2");list.add("选项3");list.add("选项4");list.add("选项5");// 添加按钮获取选中项Button button = new Button("获取选中项");button.addActionListener(e -> {int selectedIndex = list.getSelectedIndex();if (selectedIndex >= 0) {System.out.println("选中项: " + list.getItem(selectedIndex));}});frame.add(list, BorderLayout.CENTER);frame.add(button, BorderLayout.SOUTH);// 添加窗口关闭事件frame.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {System.exit(0);}});frame.setVisible(true);}
}
2. Choice 组件
java.awt.Choice
是一个单行的下拉选择菜单,用户点击后展开选项列表。
特点:
- 只显示当前选中项,点击后弹出选项列表。
- 仅支持单选。
- 占用空间小,适合选项较多的场景。
核心方法:
add(String item)
:添加选项。select(int index)
:选择指定索引的选项。select(String item)
:选择指定文本的选项。getSelectedIndex()
:获取选中项的索引。getSelectedItem()
:获取选中项的文本。
示例代码:
java
import java.awt.*;
import java.awt.event.*;public class ChoiceExample {public static void main(String[] args) {Frame frame = new Frame("AWT Choice 示例");frame.setSize(300, 200);// 创建Choice组件Choice choice = new Choice();choice.add("红色");choice.add("绿色");choice.add("蓝色");choice.add("黄色");// 添加按钮获取选中项Button button = new Button("获取颜色");button.addActionListener(e -> {String selectedColor = choice.getSelectedItem();System.out.println("选中的颜色: " + selectedColor);});frame.add(choice, BorderLayout.NORTH);frame.add(button, BorderLayout.SOUTH);// 添加窗口关闭事件frame.addWindowListener(new WindowAdapter() {public void windowClosing(WindowEvent e) {System.exit(0);}});frame.setVisible(true);}
}
3. List vs Choice 对比
特性 | List | Choice |
---|---|---|
显示方式 | 多行列表,可滚动 | 单行下拉菜单,点击展开 |
选择模式 | 支持单选和多选 | 仅支持单选 |
默认行为 | 直接显示所有选项(部分可见) | 仅显示当前选中项 |
适用场景 | 选项较少,需快速浏览和选择 | 选项较多,节省空间 |
常用方法 | getSelectedIndexes() (多选) | getSelectedItem() (单选) |
4. 事件处理
两者都可通过ItemListener
监听选择变化:
java
list.addItemListener(e -> {if (e.getStateChange() == ItemEvent.SELECTED) {System.out.println("选中: " + list.getSelectedItem());}
});choice.addItemListener(e -> {if (e.getStateChange() == ItemEvent.SELECTED) {System.out.println("选中: " + choice.getSelectedItem());}
});
5. 注意事项
- AWT 组件的线程安全:虽然 AWT 不是严格线程安全的,但简单应用通常无需特殊处理。对于复杂场景,建议在事件调度线程中操作 UI。
- Swing 替代方案:如果需要更现代的 UI 组件,可使用 Swing 的
JList
和JComboBox
,它们提供了更丰富的功能和更好的外观控制。
如果你需要更多自定义选项(如自定义渲染器或复杂布局),建议转向 Swing 或 JavaFX。
常见组件:
组件就是AWT为我们设置好的一些可以直接使用的界元素:按钮,文本框,标签,我们可以用这些帮我们写好的组件来快速拼凑出功能强大的程序
标签组件:
标签组件的基本概念
在Java中,标签组件通常用于在图形用户界面(GUI)中显示文本或图像。标签组件是不可编辑的,主要用于提供信息或描述其他组件。Java提供了多种标签组件,最常用的是JLabel
类,它属于javax.swing
包。
创建标签组件
使用JLabel
类可以轻松创建标签组件。可以通过构造函数传递文本或图像来初始化标签。以下是一个简单的示例,展示如何创建一个文本标签:
import javax.swing.JFrame;
import javax.swing.JLabel;public class LabelExample {public static void main(String[] args) {JFrame frame = new JFrame("Label Example");JLabel label = new JLabel("Hello, World!");frame.add(label);frame.setSize(300, 200);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);}
}
设置标签的文本和图像
JLabel
类提供了多种方法来设置标签的文本和图像。可以使用setText()
方法设置文本,使用setIcon()
方法设置图像。以下示例展示了如何同时设置文本和图像:
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;public class LabelWithImage {public static void main(String[] args) {JFrame frame = new JFrame("Label with Image");JLabel label = new JLabel("Java Logo");ImageIcon icon = new ImageIcon("java_logo.png");label.setIcon(icon);frame.add(label);frame.setSize(300, 200);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);}
}
标签的对齐方式
JLabel
类允许设置文本和图像的对齐方式。可以使用setHorizontalAlignment()
和setVerticalAlignment()
方法来控制标签内容的对齐方式。以下示例展示了如何设置标签的水平和垂直对齐方式:
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingConstants;public class LabelAlignment {public static void main(String[] args) {JFrame frame = new JFrame("Label Alignment");JLabel label = new JLabel("Centered Text", SwingConstants.CENTER);label.setVerticalAlignment(SwingConstants.CENTER);frame.add(label);frame.setSize(300, 200);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);}
}
标签的字体和颜色
可以通过setFont()
方法设置标签的字体,通过setForeground()
方法设置文本颜色。以下示例展示了如何设置标签的字体和颜色:
import java.awt.Color;
import java.awt.Font;
import javax.swing.JFrame;
import javax.swing.JLabel;public class LabelFontAndColor {public static void main(String[] args) {JFrame frame = new JFrame("Label Font and Color");JLabel label = new JLabel("Styled Text");Font font = new Font("Serif", Font.BOLD, 18);label.setFont(font);label.setForeground(Color.BLUE);frame.add(label);frame.setSize(300, 200);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);}
}
标签的事件处理
虽然标签组件通常不处理用户输入,但可以通过添加事件监听器来实现一些交互功能。例如,可以为标签添加鼠标点击事件监听器:
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;public class LabelClickEvent {public static void main(String[] args) {JFrame frame = new JFrame("Label Click Event");JLabel label = new JLabel("Click Me!");label.addMouseListener(new MouseAdapter() {public void mouseClicked(MouseEvent e) {label.setText("Clicked!");}});frame.add(label);frame.setSize(300, 200);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);}
}
通过以上方法,可以在Java应用程序中灵活使用标签组件,实现各种界面设计需求。
小结:
在这里我调试了许久,总结的有,如果要添加标签,最好先添加在JPanel页面中,然后再将JPanel添加进入JFrame中,并且他们的布局方式也不一样,JFrame用的是BorderLayout,JPanel用的是FlowLayout布局方式,详细可以看之前写的内容。
按钮组件
在Java中,按钮组件通常通过JButton
类来实现,它是javax.swing
包的一部分。JButton
用于创建可点击的按钮,用户可以通过点击按钮来触发特定的事件。
创建按钮
要创建一个按钮,可以使用JButton
类的构造函数。最简单的形式是创建一个带有文本标签的按钮。
import javax.swing.JButton;
import javax.swing.JFrame;
import java.awt.FlowLayout;public class ButtonExample {public static void main(String[] args) {JFrame frame = new JFrame("Button Example");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setLayout(new FlowLayout());JButton button = new JButton("Click Me");frame.add(button);frame.setSize(300, 200);frame.setVisible(true);}
}
添加事件监听器
按钮通常需要与用户交互,因此需要为按钮添加事件监听器。可以使用ActionListener
接口来处理按钮点击事件。
import javax.swing.JButton;
import javax.swing.JFrame;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class ButtonExample {public static void main(String[] args) {JFrame frame = new JFrame("Button Example");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setLayout(new FlowLayout());JButton button = new JButton("Click Me");button.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {System.out.println("Button clicked!");}});frame.add(button);frame.setSize(300, 200);frame.setVisible(true);}
}
设置按钮属性
JButton
类提供了多种方法来设置按钮的属性,例如设置按钮的文本、图标、工具提示等。
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.ImageIcon;
import java.awt.FlowLayout;public class ButtonExample {public static void main(String[] args) {JFrame frame = new JFrame("Button Example");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setLayout(new FlowLayout());JButton button = new JButton("Click Me");button.setToolTipText("This is a button");button.setIcon(new ImageIcon("icon.png"));frame.add(button);frame.setSize(300, 200);frame.setVisible(true);}
}
按钮布局
按钮可以放置在容器的不同位置,通常使用布局管理器来控制按钮的位置和大小。常见的布局管理器包括FlowLayout
、BorderLayout
、GridLayout
等。
import javax.swing.JButton;
import javax.swing.JFrame;
import java.awt.BorderLayout;public class ButtonExample {public static void main(String[] args) {JFrame frame = new JFrame("Button Example");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setLayout(new BorderLayout());JButton button1 = new JButton("North");JButton button2 = new JButton("South");JButton button3 = new JButton("East");JButton button4 = new JButton("West");JButton button5 = new JButton("Center");frame.add(button1, BorderLayout.NORTH);frame.add(button2, BorderLayout.SOUTH);frame.add(button3, BorderLayout.EAST);frame.add(button4, BorderLayout.WEST);frame.add(button5, BorderLayout.CENTER);frame.setSize(300, 200);frame.setVisible(true);}
}
通过以上方法,可以在Java应用程序中创建和使用按钮组件,并根据需要设置其属性和事件处理逻辑。
菜单栏和弹出菜单
菜单:顾名思义就是包含各种基本操作的组件,程序中我们经常使用下拉菜单:
菜单的层级结构:
MenuBar (菜单栏)
├─ Menu (文件)
│ ├─ MenuItem (新建)
│ ├─ MenuItem (打开)
│ └─ MenuItem (保存)
├─ Menu (编辑)
│ ├─ MenuItem (复制)
│ ├─ MenuItem (粘贴)
│ └─ Menu (查找)
│ └─ MenuItem (查找下一个)
└─ Menu (帮助)└─ MenuItem (关于)
下面是AWT中的菜单介绍:
在Java中,AWT(Abstract Window Toolkit)提供了创建图形用户界面(GUI)的基本工具。AWT中的菜单、弹出菜单和菜单栏是构建用户界面的重要组件。以下是对这些组件的详细介绍。
菜单栏(MenuBar)
菜单栏是窗口顶部的水平条,通常包含多个菜单。在AWT中,MenuBar
类用于创建菜单栏。菜单栏可以添加到Frame
或Dialog
中。
import java.awt.*;public class MenuBarExample {public static void main(String[] args) {JFrame frame = new JFrame("MenuBar Example");MenuBar menuBar = new MenuBar();Menu fileMenu = new Menu("File");Menu editMenu = new Menu("Edit");menuBar.add(fileMenu);menuBar.add(editMenu);frame.setMenuBar(menuBar);frame.setSize(300, 200);frame.setVisible(true);}
}
菜单(Menu)
菜单是菜单栏中的一个下拉列表,包含多个菜单项。Menu
类用于创建菜单。菜单可以包含其他菜单(子菜单)或菜单项(MenuItem
)。
import java.awt.*;public class MenuExample {public static void main(String[] args) {JFrame frame = new JFrame("MenuBar Example");MenuBar menuBar = new MenuBar();Menu fileMenu = new Menu("File");Menu editMenu = new Menu("Edit");menuBar.add(fileMenu);menuBar.add(editMenu);frame.setMenuBar(menuBar);frame.setSize(300, 200);frame.setVisible(true);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);}
}
弹出菜单(PopupMenu)
弹出菜单是用户右键点击时显示的菜单。PopupMenu
类用于创建弹出菜单。弹出菜单可以添加到任何组件中,通常与鼠标事件结合使用。
import java.awt.*;
import java.awt.event.*;public class PopupMenuExample {public static void main(String[] args) {JFrame frame = new JFrame("PopupMenu Example");PopupMenu popupMenu = new PopupMenu();MenuItem cutItem = new MenuItem("Cut");MenuItem copyItem = new MenuItem("Copy");MenuItem pasteItem = new MenuItem("Paste");popupMenu.add(cutItem);popupMenu.add(copyItem);popupMenu.add(pasteItem);frame.add(popupMenu);frame.addMouseListener(new MouseAdapter() {public void mouseClicked(MouseEvent e) {if (e.getButton() == MouseEvent.BUTTON3) {popupMenu.show(frame, e.getX(), e.getY());}}});frame.setSize(300, 200);frame.setVisible(true);}
}
菜单项(MenuItem)
菜单项是菜单中的单个选项,用户可以选择执行特定操作。MenuItem
类用于创建菜单项。菜单项可以添加到菜单或弹出菜单中。
import java.awt.*;
import java.awt.event.*;public class MenuItemExample {public static void main(String[] args) {Frame frame = new Frame("MenuItem Example");MenuBar menuBar = new MenuBar();Menu fileMenu = new Menu("File");MenuItem openItem = new MenuItem("Open");MenuItem saveItem = new MenuItem("Save");openItem.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {System.out.println("Open item clicked");}});saveItem.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {System.out.println("Save item clicked");}});fileMenu.add(openItem);fileMenu.add(saveItem);menuBar.add(fileMenu);frame.setMenuBar(menuBar);frame.setSize(300, 200);frame.setVisible(true);}
}
通过以上示例,可以了解如何在Java中使用AWT创建菜单栏、菜单、弹出菜单和菜单项。这些组件是构建用户界面的基础,能够帮助用户与应用程序进行交互。
弹出对话框:
弹出窗口:
JDialog:
继承自java.awt.Dialog类,他是从一个窗体弹出来的另一个窗体,他们JFrame类似,需要调用getContentPane将窗体转换为容器,然后在容器中设置窗体的内容。
JDialog:可以当作JFrame使用,但是必须从属于JFrame
构造函数:
- JDialog();
- JDialog(Frame f); //指定父窗口
- JDialog(Frame f,String title); //指定父窗口+标题
- JDialog关闭窗口的时候不能用DISPOSE_ON_CLOS,所以关闭大窗口会连着小的一起关闭,因为JDialog从属于JFrame.
下面演示:
package pdsu__zjh;
import javax.swing.*;
import javax.swing.JFrame;
public class Textt {public static void main(String []args) {JFrame jf=new JFrame();jf.setBounds(400,250,600,550);//设置位置,长,宽;jf.setVisible(true);//设置是否显示jf.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//关闭方式JDialog jDialog=new JDialog();jDialog.setBounds(400,250,400,250);jDialog.setVisible(true);jDialog.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);}
}
效果演示:
弹出对话框
使用JOptionPane创建弹出对话框
Java中可以通过JOptionPane
类来创建各种类型的弹出对话框。JOptionPane
提供了多种静态方法来显示消息对话框、确认对话框、输入对话框等。
import javax.swing.JOptionPane;public class DialogExample {public static void main(String[] args) {// 显示消息对话框JOptionPane.showMessageDialog(null, "这是一个消息对话框", "消息", JOptionPane.INFORMATION_MESSAGE);// 显示确认对话框int response = JOptionPane.showConfirmDialog(null, "你确定要继续吗?", "确认", JOptionPane.YES_NO_OPTION);if (response == JOptionPane.YES_OPTION) {System.out.println("用户选择了是");} else {System.out.println("用户选择了否");}// 显示输入对话框String input = JOptionPane.showInputDialog(null, "请输入你的名字:", "输入", JOptionPane.QUESTION_MESSAGE);if (input != null) {System.out.println("你输入的名字是:" + input);}}
}
自定义对话框
如果需要更复杂的对话框,可以继承JDialog
类来创建自定义对话框。这种方式允许完全控制对话框的布局和行为。
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JButton;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;public class CustomDialog extends JDialog {public CustomDialog(JFrame parent) {super(parent, "自定义对话框", true);setLayout(new FlowLayout());add(new JLabel("这是一个自定义对话框"));JButton closeButton = new JButton("关闭");closeButton.addActionListener(new ActionListener() {public void actionPerformed(ActionEvent e) {dispose();}});add(closeButton);pack();setLocationRelativeTo(parent);}public static void main(String[] args) {JFrame frame = new JFrame("主窗口");frame.setSize(300, 200);frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setVisible(true);CustomDialog dialog = new CustomDialog(frame);dialog.setVisible(true);}
}
使用JFileChooser选择文件
JFileChooser
类可以用于创建文件选择对话框,允许用户选择文件或目录。
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.filechooser.FileNameExtensionFilter;public class FileChooserExample {public static void main(String[] args) {JFileChooser fileChooser = new JFileChooser();FileNameExtensionFilter filter = new FileNameExtensionFilter("文本文件", "txt");fileChooser.setFileFilter(filter);int returnValue = fileChooser.showOpenDialog(null);if (returnValue == JFileChooser.APPROVE_OPTION) {System.out.println("选择的文件是:" + fileChooser.getSelectedFile().getAbsolutePath());}}
}
使用JColorChooser选择颜色
JColorChooser
类可以用于创建颜色选择对话框,允许用户选择颜色。
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import java.awt.Color;public class ColorChooserExample {public static void main(String[] args) {Color selectedColor = JColorChooser.showDialog(null, "选择颜色", Color.WHITE);if (selectedColor != null) {System.out.println("选择的颜色是:" + selectedColor);}}
}
通过以上方法,可以在Java应用程序中轻松创建各种类型的弹出对话框,满足不同的用户交互需求。
窗口修饰和自定义形状
一、窗口修饰(去除标题栏、边框)
步骤:
frame.setUndecorated(true)
移除默认修饰- 手动添加标题栏 / 按钮
- 实现窗口拖动逻辑
示例代码:
java
JFrame frame = new JFrame();
frame.setUndecorated(true); // 先移除默认修饰// 添加自定义标题栏和关闭按钮
JPanel titleBar = new JPanel();
titleBar.add(new JLabel("自定义标题"));
titleBar.add(new JButton("X"));// 实现拖动功能(略,见之前示例)
二、自定义窗口形状
步骤:
setUndecorated(true)
setShape(shape)
设置形状- 确保内容绘制与形状一致
示例代码(圆形窗口):
java
JFrame frame = new JFrame();
frame.setUndecorated(true); // 必须先移除默认修饰// 创建圆形面板
JPanel panel = new JPanel() {@Overrideprotected void paintComponent(Graphics g) {g.fillOval(0, 0, getWidth(), getHeight());}
};frame.setContentPane(panel);
frame.pack();// 设置窗口形状为圆形(在pack之后)
frame.setShape(new Ellipse2D.Double(0, 0, frame.getWidth(), frame.getHeight()));
三、透明窗口
步骤:
setUndecorated(true)
setOpacity(0.5f)
设置透明度(0.0-1.0)- 内容面板设为透明
示例代码:
java
frame.setUndecorated(true);
frame.setOpacity(0.8f); // 80%透明度JPanel panel = new JPanel();
panel.setBackground(new Color(255, 255, 255, 100)); // 半透明白色
frame.setContentPane(panel);
四、关键注意事项
- 顺序:必须先
setUndecorated(true)
,再设置形状 / 透明度 - 系统检查:使用前检查系统支持:
java
boolean supportsShape = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().isWindowTranslucencySupported(WindowTranslucency.PERPIXEL_TRANSPARENT);
- 性能:复杂形状 / 透明度可能影响性能
- 拖动逻辑:移除修饰后需手动实现窗口拖动(见之前示例中的
WindowDragListener
)
多面板和分割面板:
在 Java 的 Swing GUI 编程里,多面板和分割面板是组织和管理界面的重要组件。下面为你详细介绍它们的概念、用法和区别。
多面板(Multi-Panel)
多面板并非 Java 的标准术语,不过在实际应用中,它指的是将多个面板组合到一个容器里的布局方式。这种方式能够让界面结构清晰,便于管理。
常见实现方式
- 嵌套 JPanel:可以把多个 JPanel 添加到一个父容器中,每个子面板负责管理特定区域的组件。
- 卡片布局(CardLayout):这是一种特殊的布局管理器,它能让多个组件共享同一显示空间,组件之间可以像卡片一样切换。
- 选项卡面板(JTabbedPane):它会创建带有选项卡的界面,每个选项卡下面都可以放置不同的面板。
示例代码
下面是一个嵌套 JPanel 的例子:
import javax.swing.*;
import java.awt.*;public class MultiPanelExample {public static void main(String[] args) {JFrame frame = new JFrame("多面板示例");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setSize(400, 300);// 创建主面板,使用边界布局JPanel mainPanel = new JPanel(new BorderLayout());// 顶部面板 - 包含按钮JPanel topPanel = new JPanel();topPanel.add(new JButton("按钮1"));topPanel.add(new JButton("按钮2"));// 中部面板 - 包含文本区域JPanel centerPanel = new JPanel();centerPanel.add(new JTextArea(10, 30));// 将子面板添加到主面板mainPanel.add(topPanel, BorderLayout.NORTH);mainPanel.add(centerPanel, BorderLayout.CENTER);// 将主面板添加到窗口frame.setContentPane(mainPanel);frame.setVisible(true);}
}
分割面板(JSplitPane)
JSplitPane 是 Swing 提供的标准组件,其主要功能是创建一个可调整的分割线,把容器分为两个区域。用户能够通过拖动分割线来改变两个区域的大小。
关键特性
- 方向支持:支持水平分割(HORIZONTAL_SPLIT)和垂直分割(VERTICAL_SPLIT)。
- 连续重绘:在拖动分割线时,可以选择实时重绘界面或者在拖动结束后再重绘。
- 固定比例:能够设置分割线的位置,既可以使用像素值,也可以使用相对于容器大小的比例。
示例代码
下面是一个使用 JSplitPane 的例子:
java
import javax.swing.*;
import java.awt.*;public class SplitPaneExample {public static void main(String[] args) {JFrame frame = new JFrame("分割面板示例");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.setSize(600, 400);// 创建左侧面板JPanel leftPanel = new JPanel();leftPanel.add(new JList<>(new String[]{"项目1", "项目2", "项目3"}));// 创建右侧面板JPanel rightPanel = new JPanel();rightPanel.add(new JTextArea(20, 30));// 创建水平分割面板JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,leftPanel,rightPanel);// 设置分割线位置(相对于容器宽度的比例)splitPane.setDividerLocation(0.3);// 设置连续重绘,使拖动更流畅splitPane.setContinuousLayout(true);// 将分割面板添加到窗口frame.setContentPane(splitPane);frame.setVisible(true);}
}
多面板与分割面板的主要区别
特性 | 多面板(嵌套 JPanel) | 分割面板(JSplitPane) |
---|---|---|
布局方式 | 需要手动管理每个面板的大小和位置 | 自动管理两个区域,可通过拖动分割线调整 |
用户交互 | 面板大小固定,用户无法动态调整 | 用户可以实时调整两个区域的大小 |
应用场景 | 适合界面布局固定的情况,例如表单、工具栏 | 适合需要动态调整空间分配的场景,如图文混排、资源管理器 |
实现复杂度 | 需要处理多个面板的布局,相对复杂 | 只需设置一次,自动处理大部分布局逻辑 |
SWing和Awt的区别
1. 历史与定位
-
AWT(1995 年):
- Java 最早的 GUI 库,属于 Java 基础类库(JRE)的一部分。
- 称为 “重量级” 组件,依赖底层操作系统的原生窗口系统(如 Windows 的 Win32 API)。
-
Swing(1997 年):
- 作为 AWT 的扩展,属于 Java Foundation Classes (JFC)。
- 称为 “轻量级” 组件,完全由 Java 代码实现,不依赖原生窗口系统。
2. 核心架构差异
特性 | AWT(重量级) | Swing(轻量级) |
---|---|---|
组件实现 | 依赖原生窗口系统(如 Windows/Linux) | 纯 Java 实现,跨平台一致性好 |
渲染方式 | 由操作系统负责绘制 | 由 Java 虚拟机(JVM)负责绘制 |
内存占用 | 高(每个组件对应一个原生窗口句柄) | 低(共享一个窗口句柄) |
性能 | 受限于操作系统绘制效率 | 通常更高,但复杂 UI 可能有性能开销 |
外观一致性 | 与操作系统风格一致 | 可定制外观(如 Nimbus、Metal) |
3. 组件对比
组件类型 | AWT 类 | Swing 等效类 |
---|---|---|
窗口 | Frame , Dialog | JFrame , JDialog |
面板 | Panel | JPanel |
按钮 | Button | JButton |
标签 | Label | JLabel |
文本框 | TextField | JTextField |
滚动面板 | ScrollPane | JScrollPane |
菜单 | MenuBar , Menu , MenuItem | JMenuBar , JMenu , JMenuItem |
对话框 | FileDialog | JFileChooser |
4. 功能特性对比
特性 | AWT | Swing |
---|---|---|
透明效果 | 不支持 | 支持(如setOpaque(false) ) |
自定义边框 | 无内置支持 | 丰富的边框选项(BorderFactory ) |
双缓冲 | 需手动实现 | 默认启用,减少闪烁 |
事件处理 | 基于接口(如ActionListener ) | 支持匿名内部类和 Lambda 表达式 |
数据模型 | 无统一数据模型 | 支持 MVC 模式(如TableModel ) |
组件丰富度 | 基础组件 | 提供更多高级组件(如JTable , JTree ) |
主题支持 | 依赖操作系统 | 支持多种主题(如 Nimbus、Windows 风格) |
5. 线程安全性
-
AWT:
- 非线程安全,但早期 Java 版本允许在任意线程更新 UI(可能导致绘制异常)。
-
Swing:
- 严格要求在事件调度线程(Event Dispatch Thread, EDT)中操作 UI,否则可能出现竞态条件。
- 使用
SwingUtilities.invokeLater()
或SwingUtilities.invokeAndWait()
确保线程安全。
java
// 示例:在EDT中创建Swing UI
SwingUtilities.invokeLater(() -> {JFrame frame = new JFrame("线程安全示例");frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);frame.add(new JLabel("Hello, Swing!"));frame.pack();frame.setVisible(true);
});
6. 应用场景
-
选择 AWT:
- 开发简单工具或小程序。
- 需要与操作系统原生组件深度集成。
- 维护旧 Java 项目(如 JDK 1.1 时代的代码)。
-
选择 Swing:
- 开发跨平台的桌面应用。
- 需要丰富的 UI 组件(如表格、树状结构)。
- 需要自定义外观或动画效果。
- 开发复杂的企业级应用(如 IDE、数据可视化工具)。
7. 现代替代方案
虽然 Swing 和 AWT 仍被广泛使用,但 Java 的 GUI 生态已发展出更现代的框架:
-
JavaFX(自 Java 8 引入):
- 官方推荐的下一代 GUI 框架,支持 FXML、CSS 样式、3D 图形和多媒体。
- 逐渐取代 Swing 成为 Java 桌面应用的首选。
-
第三方框架:
- Apache Pivot:基于 Batik 的轻量级框架,支持多种 UI 风格。
- MigLayout:增强的布局管理器,简化复杂布局的实现。
- JGoodies Forms:提供更灵活的表单布局解决方案。
总结
维度 | AWT | Swing |
---|---|---|
年代 | 早期(JDK 1.0) | 后期(JDK 1.2+) |
技术路线 | 重量级,依赖原生系统 | 轻量级,纯 Java 实现 |
外观控制 | 受限(与系统一致) | 高度可定制 |
性能 | 低(原生调用开销) | 高(Java 优化) |
学习曲线 | 简单(基础 API) | 较复杂(更多概念) |
推荐场景 | 简单工具、原生集成 | 复杂 UI、跨平台应用 |
相关文章:
GUI图形化演示
概述 Swing组件通常被称为“轻量级组件”,他完全由Java编写,不依赖操作系统语言,他的类继承关系如下: Java.lang.Object->Java.awt.Component->Java.awt.Container->Javax.swing.JCompoment JCompoent是swing组件存放的位置&…...
Day118 | 灵神 | 二叉树 | 删点成林
Day118 | 灵神 | 二叉树 | 删点成林 1110.删点成林 1110. 删点成林 - 力扣(LeetCode) 思路: 最直接的思路就是看当前结点的值是不是在要删除的列表中,在的话删除当前结点并把左右孩子加入res中 很可惜这样是错的,…...
每周靶点:IL31、B7H3及文献分享
本期精选了《炎症中的“瘙痒”细胞因子IL31》《免疫检查点分子B7H3》《重组抗体:抗体测序和人工智能助力抗体设计》《文献分享:用于HER2特异性递送的单链Fab衍生药物偶联物》《文献分享:全长抗体、片段和双特异性格式的可开发性的比较研究》五…...
机器学习笔记——特征工程
大家好,这里是好评笔记,公主号:Goodnote,专栏文章私信限时Free。本笔记介绍机器学习中常见的特征工程方法、正则化方法和简要介绍强化学习。 文章目录 特征工程(Fzeature Engineering)1. 特征提取ÿ…...
麒麟v10 部署 MySQL 5.6.10 完整步骤
需要包的私信我 一、安装依赖(Perl环境) # 在线安装依赖 yum -y install perl perl-devel# 离线安装(需提前下载好rpm包) mkdir /data/ybn/soft/pre yum install --downloadonly --downloaddir/data/ybn/soft/pre perl perl-dev…...
digitalworld.local: DEVELOPMENT靶场
digitalworld.local: DEVELOPMENT 来自 <https://www.vulnhub.com/entry/digitalworldlocal-development,280/> 1,将两台虚拟机网络连接都改为NAT模式 2,攻击机上做namp局域网扫描发现靶机 nmap -sn 192.168.23.0/24 那么攻击机IP为192.168.23.18…...
高等数学基础(梯度下降法求函数的最小值)
梯度下降法, 一般是寻找函数极小值最常用的优化方法. 当目标函数时凸函数时, 梯度下降时全局解, 但是一般情况没办法保证是全局最优的. 通常在求最优解时, 首先会设定好步长大小进行调整, 按照上述方法对参数进行调整后就会逼近一个极小值 设函数 f ( x ) f(x) f(x)为一元连续函…...
【AI News | 20250515】每日AI进展
AI Repos 1、helix-db 专用于RAG以及AI应用的一款高性能图向量数据库:HelixDB,比Neo4j快1000倍,比TigerGraph快100倍,向量搜索性能和Qdrant相当。原生支持图形和矢量数据类型,比较适合RAG和AI应用,像知识图…...
大数据架构选型分析
选择依据 1.业务需求与技术要求 用户需要根据自己的业务需求来选择架构,如果业务对于Hadoop、Spark、Strom等关键技术有强制性依赖,选择Lambda架构可能较为合适;如果处理数据偏好于流式计算,又依赖Flink计算引擎,那么…...
C++中多重继承下的虚表结构
在 C 的多重继承 中,虚表(vtable)结构会变得更加复杂。 一、基础回顾:单继承下的虚表结构 类中含有虚函数 → 编译器生成虚表(每类一张);每个对象有一个隐藏的虚表指针(vptr&#x…...
安全巡检清单
安全巡检报告清单 引言 安全巡检是保障信息系统稳定运行和数据安全的关键环节。通过周期性的状态检查、安全扫描、日志分析和补丁管理,可以及时发现并修复潜在的安全隐患和漏洞,确保网络设备、服务器、操作系统及应用系统的高可用性和安全性。本清单旨…...
【redis】redis常见数据结构及其底层,redis单线程读写效率高于多线程的理解,
redis常用数据结构及底层 string字符串、list链表、set无序集合、zset有序集合、hash哈希 1.string 底层结构是SDS简单动态字符串 struct sdshdr {int len; // 已用长度(字符串实际长度)int free; // 剩余可用空间char buf[]; // 数组&#…...
Redis6为什么引入了多线程?
大家好,我是锋哥。今天分享关于【Redis6为什么引入了多线程?】面试题。希望对大家有帮助; Redis6为什么引入了多线程? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Redis 6 引入多线程的主要目的是提升性能…...
使用GmSSL v3.1.1实现SM2证书认证
1、首先使用gmssl命令生成根证书、客户端公私钥,然后使用根证书签发客户端证书; 2、然后编写代码完成认证功能,使用根证书验证客户端证书是否由自己签发,然后使用客户端证书验证客户端私钥对随机数的签名是否正确。 第一部分生成根…...
Spring MVC 接口的访问方法如何设置
RequestMapping 是 Spring 框架中用于映射 HTTP 请求到控制器方法的注解。它支持以下 HTTP 方法访问类型,通过 method 属性指定: GET:用于获取资源POST:用于提交数据PUT:用于更新资源DELETE:用于删除资源PA…...
虚拟网络编辑器
vmnet1 仅主机模式 hostonly 功能:虚拟机只能和宿主机通过vmnet1通信,不可连接其他网络(包括互联网) vmnet8 地址转换模式 NAT 功能:虚拟机可以和宿主通过vmnet8通信,并且可以连接其他网络,但是…...
【hadoop】Flume日志采集系统的安装部署
一、Flume安装与配置 步骤: 1、使用XFTP将Flume安装包apache-flume-1.9.0-bin.tar.gz发送到master机器的主目录。 2、解压安装包: tar -zxvf ~/apache-flume-1.9.0-bin.tar.gz 3、修改文件夹的名字,将其改为flume,或者创建软…...
Kafka快速安装与使用
引言 这篇文章是一篇Ubuntu(Linux)环境下的Kafka安装与使用教程,通过本文,你可以非常快速搭建一个kafka的小单元进行日常开发与调测。 安装步骤 下载与解压安装 首先我们需要下载一下Kafka,这里笔者采用wget指令: wget https:…...
C# 实现雪花算法(Snowflake Algorithm)详解与应用
在现代分布式系统中,生成全局唯一的标识符(ID)是一个非常重要的问题。随着微服务架构和分布式系统的普及,传统的单机数据库生成 ID 的方式已无法满足高并发和高可用的需求。为了解决这个问题,Twitter 提出了 雪花算法&…...
中间件-MQ常见问题
MQ常见问题 消息丢失消息会在哪些环节丢失应对机制 消息的顺序性消息幂等消息积压的处理 消息丢失 消息会在哪些环节丢失 网络传输环节:生产者发送消息到broker,broker中master同步消息给slave,consumer消费消息,这3个环节都是跨…...
Redis学习打卡-Day2-缓存更新策略、主动更新策略、缓存穿透、缓存雪崩、缓存击穿
缓存更新策略 对于低一致性需求:使用内存淘汰机制。例如店铺类型的查询缓存。对于高一致性需求:主动更新,并以超时剔除作为兜底方案。例如店铺详情查询的缓存。 主动更新策略(缓存读写策略) 1. Cache Aside Pattern&…...
Git - 1( 14000 字详解 )
一: Git 初识 1.1 提出问题 在工作或学习中,我们常常会面临文档管理的问题,尤其是在编写各种文档时。为了防止文档丢失或因更改失误而无法恢复,我们常常会创建多个版本的副本,例如:“报告-v1”、“报告-v…...
搭建Centos环境安装禅道
关于禅道: 禅道项目管理软件,将CMMI模型的要求有机融合到项目管理各个过程,支持Scrum、瀑布、看板和狭义IPD并支持融合使用。禅道项目管理软件功能强大,集产品管理、项目管理、质量管理、文档管理、组织管理和事务管理于一体&…...
语音识别——语音转文字
SenseVoiceSmall阿里开源大模型,SenseVoice 是具有音频理解能力的音频基础模型,包括语音识别(ASR)、语种识别(LID)、语音情感识别(SER)和声学事件分类(AEC)或…...
语音识别——声纹识别
通过将说话人的声音与数据库中的记录声音进行比对,判断说话人是否为数据库白名单中的同一人,从而完成语音验证。目前,3D-Speaker 声纹验证的效果较为出色。 3D-Speaker 是一个开源工具包,可用于单模态和多模态的说话人验证、说话…...
c++作业整理2
直接访问就是直接利用变量的地址直接进行访问。 答案:T 解析:直接访问通过变量名(实际对应内存地址)访问数据,与间接访问(通过指针)相对。 char *s"C Language"; 表示 s 是一个指向字…...
无人机屏蔽与滤波技术模块运行方式概述!
一、模块运行方式 1. 电磁屏蔽模块 动态频段干扰:通过发射与无人机通信频段(如2.4GHz、5.8GHz、GPS频段等)同频的强干扰信号,切断无人机与遥控器、图传设备间的通信链路,实现迫降或返航功能。例如便携式屏蔽器通过…...
兼顾长、短视频任务的无人机具身理解!AirVista-II:面向动态场景语义理解的无人机具身智能体系统
作者:Fei Lin 1 ^{1} 1, Yonglin Tian 2 ^{2} 2, Tengchao Zhang 1 ^{1} 1, Jun Huang 1 ^{1} 1, Sangtian Guan 1 ^{1} 1, and Fei-Yue Wang 2 , 1 ^{2,1} 2,1单位: 1 ^{1} 1澳门科技大学创新工程学院工程科学系, 2 ^{2} 2中科院自动化研究所…...
深入探索 OpenCV:从实时视频流到图像处理的实战指南
引言 在当今数字化时代,计算机视觉技术正逐渐成为推动科技发展的核心力量之一。从自动驾驶汽车到智能家居设备,从医疗影像诊断到工业自动化,计算机视觉的应用无处不在。而 OpenCV(Open Source Computer Vision Library࿰…...
Linux线程控制
POSIX线程库 与线程有关的函数构成了一个完整的系列,绝大多数函数的名字都是以“pthread_”打头的要使用这些函数库,要通过引入头文 <pthread.h>链接这些线程函数库时要使用编译器命令的“-lpthread”选项 创建线程 功能:创建⼀个新…...
软件设计师考试《综合知识》设计模式之——工厂模式与抽象工厂模式考点分析
软件设计师考试《综合知识》工厂模式与抽象工厂模式考点分析 1. 分值占比与考察趋势(75分制) 年份题量分值占总分比例核心考点2023111.33%抽象工厂模式适用场景2022222.67%工厂方法 vs 抽象工厂区别2021111.33%工厂方法模式结构2020111.33%简单工厂模式…...
携程旅行 酒店详情 token1004 分析 phantom-token
声明 本文章中所有内容仅供学习交流使用,不用于其他任何目的,抓包内容、敏感网址、数据接口等均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关! 部分python代码 这个网站有一个坑&am…...
QT——概述
<1>, Qt概述 Qt 是⼀个 跨平台的 C 图形⽤⼾界⾯应⽤程序框架 Qt ⽀持多种开发⼯具,其中⽐较常⽤的开发⼯具有:Qt Creator、Visual Studio、Eclipse. 一,Qt Creator 集成开发环境(IDE) Qt Creator 是⼀个轻量…...
uniapp-vue3项目中引入高德地图的天气展示
前言: uniapp-vue3项目中引入高德地图的天气展示 效果: 操作步骤: 1、页面上用定义我们的 当前天气信息:<view></view> 2、引入我们的map文件 <script setup>import amapFile from ../../libs/amap-wx.js …...
最新版VSCode通过SSH远程连接Ubuntu 16.04等旧版Linux的方法
根据官方文档Remote Development FAQ - Can I run VS Code Server on older Linux distributions?,自Visual Studio Code 1.99起,VSCode Remote - SSH Server由于运行库依赖更新,会无法连接到旧版Linux发行版上。但是好在官方在文档中还给了…...
Unity碰撞检测:射线与胶囊体投射/Layer(层)、LayerMask(遮罩层)
一、Physics碰撞检测 1.Physics.Raycast射线投射 Physics.Raycast 是 Unity 中用于执行射线检测(Raycasting)的方法。它允许你从一个点沿特定方向发射一条无形的“射线”,并检查这条射线是否与场景中的任何碰撞体相交。这个功能非常有用&am…...
浪潮云边协同:赋能云计算变革的强力引擎
在数字化浪潮以排山倒海之势席卷全球的当下,第五届数字中国建设峰会在福州盛大开幕。这场以“创新驱动新变革,数字引领新格局”为主题的行业盛会,宛如一座汇聚智慧与力量的灯塔,吸引了国内外众多行业精英齐聚一堂,共同…...
“傅里叶变换算法”来检测纸箱变形的简单示例
为了创建一个具有科技质感且能动态展示结果的纸箱变形检测傅里叶变换网页,下面将分别更新 HTML、CSS 和 JavaScript 文件。以下是更新后的代码: 1. HTML 文件 (index.html) <!DOCTYPE html> <html lang"zh-CN"> <head><…...
【SPIN】用Promela验证顺序程序:从断言到SPIN实战(SPIN学习系列--2)
你写了一段自认为“天衣无缝”的程序,但如何确保它真的没有bug?靠手动测试?可能漏掉边界情况;靠直觉?更不靠谱!这时候,Promela SPIN组合就像程序的“显微镜”——用形式化验证技术,…...
如何卸载并重新安装 Mozilla Firefox 浏览器
如果你在 Windows 上遇到现有的 Mozilla FireFox 安装问题,以下是重新安装 FireFox 的步骤。这可以帮助用户解决由于某些扩展或设置问题,或者不小心下载了令人讨厌的广告软件而导致的问题。虽然现在使用 Firefox 浏览器的用户在渐渐沦为小众群体,但是 Firefox 浏览器依然是最…...
Linux 后台运行的方法
Linux 后台运行的两种方法:screen 和 nohup 使用指南 如有错误,敬请指正 方法一:使用 screen 管理后台任务(推荐) 🔹 安装(如未安装) sudo apt install screen # Ubuntu/Debian …...
《无限暖暖》画质测评
《无限暖暖》作为一款采用虚幻5引擎打造的多平台畅玩、高自由度换装探索类RPG游戏,凭借其精美的画面、沉浸式操作和暖暖美丽坚毅的人设吸引了大量玩家。 在其中玩家可以通过做各样任务收集美好并感受到丰富的人生体验,暖暖所在的世界里有超多的NPC可以互…...
websocket简介与基本使用
websocket是什么 WebSocket 是一种基于 TCP 的全双工通信协议,允许客户端和服务器之间建立持久连接,实现实时、双向的数据传输。它是 HTTP 协议的补充,专为低延迟、高效率的实时通信设计。 核心特点 特性说明全双工通信客户端和服务器可以同时…...
面试题:请解释Java中的垃圾回收机制(Garbage Collection, GC),并讨论不同的垃圾回收算法及其优缺点
Java垃圾回收机制(GC) Java的垃圾回收机制负责自动管理内存,回收不再使用的对象以释放内存空间。GC通过以下步骤实现: 标记(Marking) :识别哪些对象是可达的,哪些是不可达的。清除…...
解决 Ubuntu 22.04 安装后启动卡死问题
最近在一台 PC 上安装了 Ubuntu 22.04 系统,但发现系统启动时出现问题:屏幕上出现一个旋转的小圈,旋转片刻后停止,系统无法正常进入桌面环境。经过一番排查,我找到了一种有效的解决方法,通过进入恢复模式并…...
线程的两种实现方式
线程的两种实现方式——内核支持线程(kernal Supported Thread, KST), 用户级线程(User Level Thread, ULT) 1. 内核支持线程 顾名思义,内核支持线程即为在内核支持下的那些线程,它们的创建&am…...
Python Bug 修复案例分析:asyncio 事件循环异常引发的程序崩溃 两种修复方法
在 Python 异步编程的工作中,asyncio库为我们提供了高效处理并发任务的强大工具。然而,asyncio在使用过程中也可能因为一些细节处理不当而引发 Bug。下面,我们就来深入分析一个因asyncio事件循环异常导致程序崩溃的典型案例。兴趣的友友可以借…...
TCP(传输控制协议)建立连接的过程
TCP(传输控制协议)建立连接的过程称为 三次握手(Three-Way Handshake)。这是为了确保通信双方能够可靠地建立连接,并同步初始序列号。以下是详细步骤: 三次握手过程(通俗比喻:打电话…...
(十九)Java集合框架深度解析:从基础到高级应用
一、集合框架概述 1.1 什么是集合框架 Java集合框架(Java Collections Framework, JCF)是Java语言中用于表示和操作集合的一套标准化体系结构。它提供了一组接口、实现类和算法,用于存储和操作对象组,解决了数组在存储对象时的诸多限制。 集合框架的主…...
数据结构与算法-线性表-单链表(Linked List)
1 线性表 1.2 单链表(Linked List) 顺序表在内存中是连续的进行存储,可以随机获取某个元素,但是在插入和删除元素的时候就非常不方便,需要移动很多相关的元素,链表就可以解决这个问题。 链表就是每个节点…...