一,关闭窗口
1.setDefaultCloseOperation()
是 JFrame
类的方法,用于定义当用户关闭窗口时,程序的行为。
四种方式:
JFrame.EXIT_ON_CLOSE
: 程序会退出并结束整个应用。JFrame.HIDE_ON_CLOSE
: 窗口隐藏,但程序会继续运行。JFrame.DISPOSE_ON_CLOSE
: 关闭当前窗口时会释放资源,但不退出程序。JFrame.DO_NOTHING_ON_CLOSE
: 什么也不做,通常需要你自己定义关闭事件的处理逻辑。
二,图像
1. 图标(Icon)
- 定义:
Icon
是一个接口,用于表示一个图形图像,它可以是任何形式的图标(比如 PNG、JPEG 格式的图片)。 - 用途:
Icon
主要用于显示图像、图标或其他视觉元素,它没有显示文本的功能。ImageIcon
是Icon
接口的常见实现,用于加载和显示图片。 - 工作方式:图标通常不会包含文本,它只表示一个视觉元素,通常作为图形界面的装饰或代表某个对象、功能的符号。例如,文件的图标、按钮上的图标等。
- 常用类:
ImageIcon
是一个实现了Icon
接口的类,常用于加载图像。
ImageIcon icon = new ImageIcon("path/to/your/image.png");
Icon
是 Java Swing 中用来表示图标的接口,主要有以下方法:
1. paintIcon(Component c, Graphics g, int x, int y)
该方法用于绘制图标。它会在指定的 x
和 y
坐标位置绘制图标。
Component c
:绘制图标的组件(通常是组件的父容器,如JLabel
)。Graphics g
:用于绘制图标的图形上下文。int x, int y
:指定绘制图标的左上角位置。
Swing 提供了几个实现了 Icon
接口的常用类:
1. ImageIcon
ImageIcon
是最常用的 Icon
实现类之一,通常用于显示图像图标。你可以通过 ImageIcon
类加载图像文件并创建图标对象。
ImageIcon icon = new ImageIcon("path/to/image.png");
//构造方法
// 从文件路径加载图标
public ImageIcon(String filename);
// 从 URL 加载图标
public ImageIcon(URL location);
// 从图像对象加载图标
public ImageIcon(Image image);
对于文件路径的选择,可以是局部路径(相对路径)或者全局路径(绝对路径),具体取决于你项目的需求和文件的存放位置。
- 相对路径(局部路径):适用于开发和在项目中使用资源文件时,不依赖于操作系统环境。适合项目部署和资源管理。
- 绝对路径(全局路径):适用于路径固定的情况,但不适合跨平台或打包部署。
getClass().getResource()
:最佳实践,尤其在构建 JAR 包时,能够确保资源文件随项目一起打包并且可以跨平台使用。
在大多数情况下,推荐使用相对路径或 getResource()
来加载资源文件,这样可以使得代码更具可移植性。
2. EmptyIcon
EmptyIcon
是 Icon
接口的一个简单实现,什么也不绘制,宽度和高度都为零。它可以用于占位,或者在某些情况下需要提供一个不绘制内容的图标时使用。
Icon emptyIcon = new EmptyIcon(16); // 创建一个 16x16 的空图标
//构造方法
public EmptyIcon(int width, int height); // 指定空图标的宽度和高度
3. Icon
接口与常见组件的结合
Icon
经常与 JLabel
、JButton
等 Swing 组件结合使用,来显示图标。
//JLabel:JLabel 可以通过 setIcon(Icon icon) 方法设置图标。
ImageIcon icon = new ImageIcon("icon.png");
JLabel label = new JLabel("This is an icon:", icon, JLabel.CENTER);
//JButton:JButton 也可以通过 setIcon(Icon icon) 方法设置图标。
ImageIcon icon = new ImageIcon("button_icon.png");
JButton button = new JButton("Click me", icon);
三,滚动窗格
JScrollPane
实际上是一个容器,用来包裹其他组件。通过 JScrollPane
添加组件时,需要传入要滚动的组件作为参数,而不是通过 add
方法手动添加。
scrollPane.add(textArea); // 错误:add 不适用于 JScrollPane
//正确:
JTextArea textArea = new JTextArea(8, 40);
// 创建滚动窗格,将 textArea 包裹在其中
JScrollPane scrollPane = new JScrollPane(textArea);
// 将滚动窗格添加到面板中
panelCenter.add(scrollPane, BorderLayout.CENTER);
四,监听器(Listener)
监听器(Listener)是一种设计模式,用于处理和响应事件。在图形用户界面(GUI)编程中,监听器通常是指一类对象,它负责等待并响应用户与界面控件的交互操作(如按钮点击、键盘输入、鼠标移动等)。这些操作被称为事件(Event)。
1,事件和监听器的工作原理
-
事件源(Event Source):这是触发事件的组件或对象,比如一个按钮、一个文本框等。当用户与这些组件进行交互时,就会触发事件。
-
事件(Event):当某个交互发生时,事件源会产生一个事件。这可以是用户点击按钮、按下键盘、移动鼠标等。
-
监听器(Listener):监听器会等待这些事件,并在事件发生时响应它们。监听器通常是一个实现了某个事件处理接口的对象,例如
ActionListener
、MouseListener
、KeyListener
等。 -
事件处理(Event Handling):当事件发生时,事件源会通知与之关联的监听器,监听器的处理方法(如
actionPerformed()
、mouseClicked()
)就会被调用来执行相应的操作。
五,invokeLater
invokeLater
是 Swing 中的一个方法,它属于 javax.swing.SwingUtilities
类,作用是在 事件调度线程 (Event Dispatch Thread, EDT) 上安排执行某个任务。Swing 是一个单线程模型(单线程UI),这意味着所有与 UI 相关的操作(例如更新界面、处理用户事件等)应该在事件调度线程上执行,以确保线程安全性。
为什么需要 invokeLater
?
在 Swing 中,任何更新界面或交互的操作都应该在事件调度线程上执行。如果你直接在其他线程(比如主线程或后台线程)中进行 UI 更新,可能会导致界面不稳定或者引发线程安全问题。invokeLater
的作用就是将任务安排到事件调度线程,确保线程安全地更新界面。
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// 在这里更新UI组件
}
});
Runnable
是一个包含run()
方法的接口,run()
方法中包含了你要在事件调度线程中执行的任务。invokeLater
会将Runnable
任务放到事件调度线程的队列中等待执行。
使用 invokeLater
的常见场景
-
创建 GUI 界面:通常在程序启动时,我们希望在事件调度线程中创建和显示界面,避免在其他线程中直接操作 Swing 组件。
-
更新界面:如果你在后台线程中执行某些任务,并希望在任务完成后更新界面(比如显示进度条或更新标签内容),就应该使用
invokeLater
。
六,窗口偏移
方法
- 获取原窗口的位置。
- 根据原窗口的位置偏移一定的距离,设置新窗口的位置。
//假设你有一个主窗口 frame1,并且想要在它的基础上,创建一个偏移一定位置的新窗口 frame2。
import javax.swing.*;
public class WindowOffsetExample {
public static void main(String[] args) {
// 在事件调度线程中创建第一个窗口
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
JFrame frame1 = new JFrame("Main Window");
frame1.setSize(400, 300);
frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame1.setVisible(true);
// 获取第一个窗口的屏幕位置
int x1 = frame1.getX();
int y1 = frame1.getY();
// 在第一个窗口的基础上,创建一个偏移的新窗口
JFrame frame2 = new JFrame("New Window");
frame2.setSize(300, 200);
// 偏移量:例如向右偏移 50 像素,向下偏移 50 像素
int offsetX = 50;
int offsetY = 50;
// 设置新窗口的位置,使其与第一个窗口稍微偏移
frame2.setLocation(x1 + offsetX, y1 + offsetY);
frame2.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame2.setVisible(true);
}
});
}
}
解释
-
获取原窗口位置:
frame1.getX()
和frame1.getY()
获取原窗口的屏幕位置(相对于屏幕左上角的坐标)。 -
设置新窗口位置:在
frame2.setLocation()
中,x1 + offsetX
和y1 + offsetY
分别表示原窗口的 X 和 Y 坐标加上一个偏移量(如 50 像素)。这会将新窗口放置在原窗口的右下方或其他指定位置。
常见的偏移方式
- 水平偏移:通过增加 X 坐标来使新窗口偏移到右边。
- 垂直偏移:通过增加 Y 坐标来使新窗口偏移到底部。
- 组合偏移:通过同时增加 X 和 Y 坐标,使新窗口在原窗口的右下方或其他角落显示。
总结
通过 setLocation()
方法,可以控制新窗口的位置。通过计算原窗口的坐标,并加上一个偏移量,能够让新窗口与老窗口保持一定的距离,从而方便区分不同的窗口。
七,边框
常见的边框类型
LineBorder
:简单的实线边框。EtchedBorder
:刻蚀边框,常见于默认的按钮边框。TitledBorder
:有标题的边框。EmptyBorder
:无边框,但可用于设置内边距。BevelBorder
:具有凹凸效果的边框,模拟按钮和控件的按下效果。CompoundBorder
:复合边框,它将两个边框组合成一个边框。
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;
public class LineBorderExample {
public static void main(String[] args) {
JFrame frame = new JFrame("Line Border Example");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
JPanel panel = new JPanel();
panel.setBorder(new LineBorder(Color.RED, 5)); // 设置红色5像素宽的边框
panel.add(new JLabel("这是一个带有LineBorder的面板"));
//JPanel panel = new JPanel();
//panel.setBorder(new EtchedBorder(EtchedBorder.LOWERED)); // 设置下凹效果
//panel.add(new JLabel("这是一个带有EtchedBorder的面板"));
//JPanel panel = new JPanel();
//panel.setBorder(new TitledBorder("面板标题"));
//panel.add(new JLabel("这是一个带有TitledBorder的面板"));
//JPanel panel = new JPanel();
//panel.setBorder(new EmptyBorder(10, 20, 10, 20)); // 设置上下左右内边距
//panel.add(new JLabel("这是一个带有EmptyBorder的面板"));
//JPanel panel = new JPanel();
//panel.setBorder(new BevelBorder(BevelBorder.RAISED)); // 设置凸起效果
//panel.add(new JLabel("这是一个带有BevelBorder的面板"));
//JPanel panel = new JPanel();
// 将LineBorder和EmptyBorder组合成一个复合边框
//panel.setBorder(new CompoundBorder(new LineBorder(Color.BLACK, 5),
new EmptyBorder(10, 10, 10, 10)));
frame.add(panel);
frame.setVisible(true);
}
}
八,菜单
1,菜单项
创建菜单通常是通过使用 JMenuBar
(菜单条)、JMenu
(菜单)和 JMenuItem
(菜单项)来实现的。
基本结构:
JMenuBar
是整个菜单的容器,放在JFrame
的顶部。JMenu
表示菜单(例如,"文件"、"编辑"等)。JMenuItem
是菜单中的具体项(例如,“打开”或“退出”)。
2,复选框和单选按钮菜单项
import javax.swing.*;
import java.awt.event.*;
public class MenuExample {
public static void main(String[] args) {
// 创建 JFrame
JFrame frame = new JFrame("菜单栏示例");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
// 创建菜单栏
JMenuBar menuBar = new JMenuBar();
// 创建“设置”菜单
JMenu settingsMenu = new JMenu("设置");
// 添加复选框菜单项
JCheckBoxMenuItem checkboxItem = new JCheckBoxMenuItem("启用特性");
checkboxItem.setSelected(true); // 默认选中
checkboxItem.addActionListener(e -> {
if (checkboxItem.isSelected()) {
System.out.println("启用了特性");
} else {
System.out.println("禁用了特性");
}
});
settingsMenu.add(checkboxItem);
// 创建按钮组,确保单选按钮只能选择一个
ButtonGroup group = new ButtonGroup();
// 添加单选按钮菜单项
JRadioButtonMenuItem radioItem1 = new JRadioButtonMenuItem("选项 1");
JRadioButtonMenuItem radioItem2 = new JRadioButtonMenuItem("选项 2");
radioItem1.setSelected(true); // 默认选中第一个选项
// 将单选按钮添加到按钮组
group.add(radioItem1);
group.add(radioItem2);
settingsMenu.add(radioItem1);
settingsMenu.add(radioItem2);
// 将设置菜单添加到菜单栏
menuBar.add(settingsMenu);
// 将菜单栏设置到 JFrame
frame.setJMenuBar(menuBar);
// 显示窗口
frame.setVisible(true);
}
}
3,工具栏和工具提示
import javax.swing.*;
import java.awt.event.*;
public class TooltipExample {
public static void main(String[] args) {
// 创建主窗口
JFrame frame = new JFrame("工具提示示例");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(400, 300);
// 创建工具栏
JToolBar toolBar = new JToolBar("工具栏");
// 创建按钮并设置工具提示
JButton newButton = new JButton("新建");
newButton.setToolTipText("创建一个新文件");
JButton saveButton = new JButton("保存");
saveButton.setToolTipText("保存当前文件");
JButton openButton = new JButton("打开");
openButton.setToolTipText("打开一个现有文件");
// 添加按钮到工具栏
toolBar.add(newButton);
toolBar.add(saveButton);
toolBar.add(openButton);
// 将工具栏添加到窗口
frame.getContentPane().add(toolBar, "North");
// 显示窗口
frame.setVisible(true);
}
}
九,布局管理
1,以下方法设置组件大小:
JButton button = new JButton("Click Me");
button.setPreferredSize(new Dimension(200, 100)); // 设置首选大小
button.setMinimumSize(new Dimension(100, 50)); // 设置最小大小
button.setMaximumSize(new Dimension(400, 200)); // 设置最大大小
2,布局管理器的影响或使用 setSize()
如果采用布局管理器,如 FlowLayout
、BorderLayout
、GridLayout
等,它们会根据容器的大小、组件的 PreferredSize
等属性来自动调整组件的大小。(具有不可控性,可能会不显示出来)
也可以直接调用组件的 setSize()
方法来设置组件的大小,但这通常不推荐,因为它会忽略布局管理器的计算结果,可能会导致不一致的行为。
button.setSize(200, 100); // 强制设置大小
请注意,setSize()
直接设置组件的大小通常不会生效,除非你禁用了布局管理器:
JPanel panel = new JPanel();
panel.setLayout(null); // 禁用布局管理器
JButton button = new JButton("Click Me");
button.setBounds(50, 50, 200, 100); // 设置按钮的位置和大小
panel.add(button);
3,容器大小调节
容器的大小通常是通过设置容器的 setPreferredSize()
或通过父容器来调整的。例如:
JFrame frame = new JFrame();
frame.setPreferredSize(new Dimension(800, 600)); // 设置窗口首选大小
frame.pack(); // 根据首选大小调整窗口大小
frame.setVisible(true);
总结
- 组件的大小可以通过设置
PreferredSize
、MinimumSize
、MaximumSize
来调节,但最终大小会受到布局管理器的影响。 - 容器的大小可以通过
setPreferredSize()
或直接调用pack()
方法来调整。 - 如果希望手动控制布局,可以禁用布局管理器,使用
setBounds()
来直接设置组件的位置和大小。
总之,容器和组件的大小是可以调节的,但如何调节要根据具体的需求和布局方式来决定。