Java 窗口
在Java GUI编程中,窗口是用户界面的基础组件,它为应用程序提供了一个可视化的交互环境。无论是简单的对话框还是复杂的多文档界面,都离不开窗口的支持。本文将全面介绍Java窗口的基本概念、创建方法以及相关操作。
什么是Java窗口?
Java窗口是一个图形化的容器,可以容纳各种UI组件(如按钮、文本框、标签等)。在Java中,窗口通常通过JFrame
、JDialog
或JWindow
等类来实现。其中:
JFrame
: 标准窗口,带有标题栏、边框、最小化/最大化/关闭按钮JDialog
: 对话框窗口,通常用于临时信息展示或用户输入JWindow
: 无边框窗口,不带任何窗口装饰
创建基本窗口
让我们从创建一个基本的JFrame
窗口开始:
import javax.swing.*;
public class SimpleWindow {
public static void main(String[] args) {
// 创建JFrame实例
JFrame frame = new JFrame("我的第一个窗口");
// 设置窗口大小
frame.setSize(400, 300);
// 设置关闭窗口时的操作
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置窗口位置为屏幕中央
frame.setLocationRelativeTo(null);
// 显示窗口
frame.setVisible(true);
}
}
运行上述代码,将显示一个标题为"我的第一个窗口",大小为400x300像素的窗口。
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
设置了关闭窗口时应用程序也会终止。如果不设置此项,关闭窗口后Java程序仍会在后台运行。
窗口布局管理
Java提供了几种布局管理器,用于控制窗口中组件的排列方式:
- BorderLayout: 将组件放在东、西、南、北、中五个区域
- FlowLayout: 按照添加顺序依次排列组件
- GridLayout: 将组件排列在网格中
- BoxLayout: 在水平或垂直方向上排列组件
- CardLayout: 像卡片一样显示组件,一次只显示一个
- GridBagLayout: 最灵活的布局管理器,允许组件占据不同的行和列
下面是一个使用BorderLayout
的例子:
import javax.swing.*;
import java.awt.*;
public class BorderLayoutExample {
public static void main(String[] args) {
JFrame frame = new JFrame("BorderLayout示例");
// 默认情况下,JFrame使用BorderLayout
// 添加组件到不同位置
frame.add(new JButton("北"), BorderLayout.NORTH);
frame.add(new JButton("南"), BorderLayout.SOUTH);
frame.add(new JButton("东"), BorderLayout.EAST);
frame.add(new JButton("西"), BorderLayout.WEST);
frame.add(new JButton("中"), BorderLayout.CENTER);
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
窗口事件处理
窗口可以响应各种事件,例如打开、关闭、最小化等。我们可以通过添加WindowListener
来处理这些事件:
import javax.swing.*;
import java.awt.event.*;
public class WindowEventExample {
public static void main(String[] args) {
JFrame frame = new JFrame("窗口事件示例");
frame.addWindowListener(new WindowAdapter() {
@Override
public void windowOpened(WindowEvent e) {
System.out.println("窗口已打开");
}
@Override
public void windowClosing(WindowEvent e) {
System.out.println("窗口正在关闭");
}
@Override
public void windowClosed(WindowEvent e) {
System.out.println("窗口已关闭");
}
@Override
public void windowIconified(WindowEvent e) {
System.out.println("窗口已最小化");
}
@Override
public void windowDeiconified(WindowEvent e) {
System.out.println("窗口已还原");
}
});
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
自定义窗口外观
我们可以通过多种方式自定义窗口的外观:
import javax.swing.*;
import java.awt.*;
public class CustomWindowExample {
public static void main(String[] args) {
JFrame frame = new JFrame("自定义窗口");
// 设置窗口图标
ImageIcon icon = new ImageIcon("icon.png");
frame.setIconImage(icon.getImage());
// 设置窗口背景颜色
Container contentPane = frame.getContentPane();
contentPane.setBackground(Color.LIGHT_GRAY);
// 禁止窗口调整大小
frame.setResizable(false);
// 设置窗口总是在最前面
frame.setAlwaysOnTop(true);
frame.setSize(400, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
对话框窗口
对话框是一种特殊类型的窗口,通常用于显示消息或获取用户输入:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class DialogExample {
public static void main(String[] args) {
JFrame mainFrame = new JFrame("主窗口");
JButton btnShowDialog = new JButton("显示对话框");
btnShowDialog.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// 创建自定义对话框
JDialog dialog = new JDialog(mainFrame, "自定义对话框", true); // true表示模态
dialog.setLayout(new FlowLayout());
dialog.add(new JLabel("这是一个自定义对话框"));
JButton btnClose = new JButton("关闭");
btnClose.addActionListener(evt -> dialog.dispose());
dialog.add(btnClose);
dialog.setSize(300, 150);
dialog.setLocationRelativeTo(mainFrame);
dialog.setVisible(true);
}
});
mainFrame.setLayout(new FlowLayout());
mainFrame.add(btnShowDialog);
mainFrame.setSize(400, 300);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
}
Swing还提供了几种预定义的对话框:
// 消息对话框
JOptionPane.showMessageDialog(null, "这是一条信息", "信息", JOptionPane.INFORMATION_MESSAGE);
// 确认对话框
int result = JOptionPane.showConfirmDialog(null, "确定要执行此操作吗?", "确认", JOptionPane.YES_NO_OPTION);
// 输入对话框
String input = JOptionPane.showInputDialog(null, "请输入您的名字:", "输入", JOptionPane.QUESTION_MESSAGE);
// 选项对话框
Object[] options = {"选项一", "选项二", "选项三"};
int choice = JOptionPane.showOptionDialog(null, "请选择一个选项", "选择",
JOptionPane.DEFAULT_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options[0]);
多文档界面(MDI)
多文档界面允许在一个主窗口内打开多个文档窗口。在Swing中,可以使用JDesktopPane
和JInternalFrame
实现MDI:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class MDIExample {
public static void main(String[] args) {
JFrame mainFrame = new JFrame("多文档界面示例");
// 创建桌面面板
JDesktopPane desktop = new JDesktopPane();
mainFrame.setContentPane(desktop);
// 创建菜单栏
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("文件");
JMenuItem newItem = new JMenuItem("新建窗口");
fileMenu.add(newItem);
menuBar.add(fileMenu);
mainFrame.setJMenuBar(menuBar);
// 为菜单项添加事件
newItem.addActionListener(new ActionListener() {
private int windowCount = 1;
@Override
public void actionPerformed(ActionEvent e) {
// 创建内部窗口
JInternalFrame internalFrame = new JInternalFrame(
"文档 " + windowCount++, // 标题
true, // 可调整大小
true, // 可关闭
true, // 可最大化
true // 可最小化
);
// 设置内部窗口内容
internalFrame.setContentPane(new JLabel("这是一个内部窗口", JLabel.CENTER));
internalFrame.setSize(250, 150);
internalFrame.setLocation(30 * (windowCount-1), 30 * (windowCount-1));
internalFrame.setVisible(true);
// 将内部窗口添加到桌面面板
desktop.add(internalFrame);
try {
internalFrame.setSelected(true);
} catch (java.beans.PropertyVetoException ex) {
ex.printStackTrace();
}
}
});
mainFrame.setSize(800, 600);
mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
mainFrame.setLocationRelativeTo(null);
mainFrame.setVisible(true);
}
}
实际案例:简单的记事本应用
下面是一个简单的记事本应用,展示了Java窗口的实际应用:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class SimpleNotepad {
public static void main(String[] args) {
JFrame frame = new JFrame("简易记事本");
// 创建文本区域
JTextArea textArea = new JTextArea();
textArea.setFont(new Font("宋体", Font.PLAIN, 14));
JScrollPane scrollPane = new JScrollPane(textArea);
frame.add(scrollPane, BorderLayout.CENTER);
// 创建菜单栏
JMenuBar menuBar = new JMenuBar();
frame.setJMenuBar(menuBar);
// 文件菜单
JMenu fileMenu = new JMenu("文件");
menuBar.add(fileMenu);
JMenuItem newItem = new JMenuItem("新建");
fileMenu.add(newItem);
newItem.addActionListener(e -> textArea.setText(""));
JMenuItem openItem = new JMenuItem("打开");
fileMenu.add(openItem);
openItem.addActionListener(e -> {
JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showOpenDialog(frame);
if (result == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
textArea.setText("");
String line;
while ((line = reader.readLine()) != null) {
textArea.append(line + "\n");
}
} catch (IOException ex) {
JOptionPane.showMessageDialog(frame, "读取文件时发生错误: " + ex.getMessage(),
"错误", JOptionPane.ERROR_MESSAGE);
}
}
});
JMenuItem saveItem = new JMenuItem("保存");
fileMenu.add(saveItem);
saveItem.addActionListener(e -> {
JFileChooser fileChooser = new JFileChooser();
int result = fileChooser.showSaveDialog(frame);
if (result == JFileChooser.APPROVE_OPTION) {
File file = fileChooser.getSelectedFile();
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
writer.write(textArea.getText());
} catch (IOException ex) {
JOptionPane.showMessageDialog(frame, "保存文件时发生错误: " + ex.getMessage(),
"错误", JOptionPane.ERROR_MESSAGE);
}
}
});
fileMenu.addSeparator();
JMenuItem exitItem = new JMenuItem("退出");
fileMenu.add(exitItem);
exitItem.addActionListener(e -> {
int confirm = JOptionPane.showConfirmDialog(frame, "确定要退出吗?",
"确认退出", JOptionPane.YES_NO_OPTION);
if (confirm == JOptionPane.YES_OPTION) {
System.exit(0);
}
});
// 编辑菜单
JMenu editMenu = new JMenu("编辑");
menuBar.add(editMenu);
JMenuItem cutItem = new JMenuItem("剪切");
editMenu.add(cutItem);
cutItem.addActionListener(e -> textArea.cut());
JMenuItem copyItem = new JMenuItem("复制");
editMenu.add(copyItem);
copyItem.addActionListener(e -> textArea.copy());
JMenuItem pasteItem = new JMenuItem("粘贴");
editMenu.add(pasteItem);
pasteItem.addActionListener(e -> textArea.paste());
// 设置窗口属性
frame.setSize(800, 600);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
总结
本教程介绍了Java窗口编程的基础知识,包括:
- 创建基本窗口
- 窗口布局管理
- 窗口事件处理
- 自定义窗口外观
- 对话框窗口
- 多文档界面
- 实际应用案例
通过掌握这些基础知识,你可以开始开发自己的Java GUI应用程序。随着经验的积累,你可以探索更多高级技术,如自定义组件、拖放功能、复杂的数据展示等。
附加资源与练习
练习题
- 创建一个带有标题和图标的简单窗口。
- 实现一个计算器窗口,使用
GridLayout
布局按钮。 - 创建一个窗口,当用户尝试关闭时,显示确认对话框。
- 实现一个带有菜单栏、工具栏和状态栏的完整窗口框架。
- 扩展记事本应用,添加查找/替换、字体设置等功能。
进阶学习资源
- Oracle的Java Swing教程:https://docs.oracle.com/javase/tutorial/uiswing/
- Java GUI编程:更深入的学习窗口管理和组件开发
- Java图形库:JavaFX、SWT等替代Swing的现代GUI框架
- 设计模式:在GUI编程中应用MVC等设计模式
Swing是Java传统的GUI库,虽然功能完善但在现代应用开发中,特别是对于要求高性能和现代外观的应用,JavaFX可能是更好的选择。不过,学习Swing仍然有助于理解GUI编程的基本概念。