我们将使用 Java 最经典、最基础的 GUI 工具包:Java Swing。

项目目标
创建一个简单的文本编辑器,具备以下功能:
- 一个多行文本区域用于输入和编辑文本。
- 一个菜单栏,包含“文件”菜单。
- “文件”菜单下有“新建”、“打开”、“保存”和“退出”功能。
- 能够保存和加载
.txt文本文件。
第一步:开发环境准备
在开始编码前,请确保你已经安装并配置好了 Java 开发环境。
-
安装 JDK (Java Development Kit):
- 前往 Oracle 官网或 OpenJDK 官网下载并安装最新版本的 JDK。
- 推荐版本: JDK 8, 11, 17 或 21,这些是长期支持版本,稳定且广泛使用。
-
配置环境变量:
(图片来源网络,侵删)JAVA_HOME: 指向你的 JDK 安装目录。Path: 在Path变量中添加%JAVA_HOME%\bin(Windows) 或$JAVA_HOME/bin(macOS/Linux),这样你就可以在任何目录下使用javac和java命令。
-
选择一个代码编辑器 (IDE):
- IntelliJ IDEA (社区版免费): 非常强大,智能提示和调试功能一流。
- Eclipse: 老牌 Java IDE,功能全面,免费开源。
- VS Code: 配合 Java 扩展插件,也可以进行 Java 开发,轻量高效。
- 记事本/Notepad++: 如果你喜欢纯粹的手动编码,也可以使用。
-
验证安装:
- 打开命令行(Windows 的
cmd或 PowerShell,macOS/Linux 的Terminal)。 - 输入
java -version和javac -version,如果都显示版本号,说明环境配置成功。
- 打开命令行(Windows 的
第二步:创建项目并编写代码
我们将创建一个名为 NotepadApp.java 的文件。
项目结构
在你的 IDE 中创建一个新的 Java 项目,并创建一个 NotepadApp.java 文件。

完整代码
这是实现一个简单记事本所需的全部 Java Swing 代码,你可以直接复制粘贴到你的 NotepadApp.java 文件中。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
public class NotepadApp extends JFrame {
// GUI 组件
private JTextArea textArea;
private JMenuBar menuBar;
private JMenu fileMenu;
private JMenuItem newItem, openItem, saveItem, exitItem;
// 文件相关
private File currentFile; // 当前操作的文件
public NotepadApp() {
// 1. 设置窗口基本属性
setTitle("Java 记事本");
setSize(800, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭窗口时退出程序
setLocationRelativeTo(null); // 窗口居中
// 2. 创建菜单栏
createMenuBar();
// 3. 创建文本区域
textArea = new JTextArea();
// 添加滚动条,当文本超出可视区域时出现
JScrollPane scrollPane = new JScrollPane(textArea);
add(scrollPane, BorderLayout.CENTER);
// 4. 添加窗口关闭事件监听器
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
// 在关闭前检查是否有未保存的更改
if (textArea.hasBeenModified()) { // 注意:JTextArea 本身没有 hasBeenModified 方法,这里仅为演示逻辑
// 实际项目中需要自己实现一个修改状态标志
int option = JOptionPane.showConfirmDialog(
NotepadApp.this,
"您有未保存的更改,是否保存?",
"提示",
JOptionPane.YES_NO_CANCEL_OPTION
);
if (option == JOptionPane.YES_OPTION) {
saveFile(); // 调用保存方法
} else if (option == JOptionPane.CANCEL_OPTION) {
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // 取消关闭
}
}
}
});
}
/**
* 创建菜单栏
*/
private void createMenuBar() {
menuBar = new JMenuBar();
// 文件菜单
fileMenu = new JMenu("文件");
// 新建菜单项
newItem = new JMenuItem("新建");
newItem.addActionListener(e -> newFile());
fileMenu.add(newItem);
// 打开菜单项
openItem = new JMenuItem("打开");
openItem.addActionListener(e -> openFile());
fileMenu.add(openItem);
// 保存菜单项
saveItem = new JMenuItem("保存");
saveItem.addActionListener(e -> saveFile());
fileMenu.add(saveItem);
fileMenu.addSeparator(); // 添加分隔线
// 退出菜单项
exitItem = new JMenuItem("退出");
exitItem.addActionListener(e -> exitApp());
fileMenu.add(exitItem);
menuBar.add(fileMenu);
setJMenuBar(menuBar);
}
/**
* 新建文件
*/
private void newFile() {
// 如果当前文本区域有内容,提示是否保存
// ... (这里可以添加保存提示逻辑,与关闭窗口类似)
textArea.setText("");
currentFile = null;
setTitle("Java 记事本 - 新文件");
}
/**
* 打开文件
*/
private void openFile() {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("打开文件");
int userSelection = fileChooser.showOpenDialog(this);
if (userSelection == JFileChooser.APPROVE_OPTION) {
currentFile = fileChooser.getSelectedFile();
try (BufferedReader reader = new BufferedReader(new FileReader(currentFile))) {
textArea.read(reader, null); // JTextArea 的 read 方法可以从 Reader 读取内容
setTitle("Java 记事本 - " + currentFile.getName());
} catch (IOException ex) {
JOptionPane.showMessageDialog(this, "打开文件时出错: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
}
}
}
/**
* 保存文件
*/
private void saveFile() {
if (currentFile == null) {
// 如果是新建的文件,弹出另存为对话框
saveAsFile();
} else {
writeToFile(currentFile);
}
}
/**
* 另存为
*/
private void saveAsFile() {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setDialogTitle("另存为");
int userSelection = fileChooser.showSaveDialog(this);
if (userSelection == JFileChooser.APPROVE_OPTION) {
currentFile = fileChooser.getSelectedFile();
// 如果用户没有输入扩展名,可以自动添加 .txt
if (!currentFile.getName().toLowerCase().endsWith(".txt")) {
currentFile = new File(currentFile.getParentFile(), currentFile.getName() + ".txt");
}
writeToFile(currentFile);
}
}
/**
* 将文本区域的内容写入文件
* @param file 要写入的文件
*/
private void writeToFile(File file) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
textArea.write(writer); // JTextArea 的 write 方法可以将内容写入 Writer
setTitle("Java 记事本 - " + file.getName());
JOptionPane.showMessageDialog(this, "文件保存成功!", "成功", JOptionPane.INFORMATION_MESSAGE);
} catch (IOException ex) {
JOptionPane.showMessageDialog(this, "保存文件时出错: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
}
}
/**
* 退出应用程序
*/
private void exitApp() {
// 这里可以添加检查未保存更改的逻辑
System.exit(0);
}
// 主方法,程序入口
public static void main(String[] args) {
// 使用 SwingUtilities.invokeLater 确保 GUI 创建在事件分发线程中
SwingUtilities.invokeLater(() -> {
NotepadApp notepad = new NotepadApp();
notepad.setVisible(true); // 显示窗口
});
}
}
第三步:代码详解
主类 NotepadApp
它继承自 JFrame,JFrame 是 Swing 中一个顶层窗口容器,我们所有的 GUI 组件都会放在这个窗口里。
GUI 组件
JTextArea: 一个多行文本编辑区域,是记事本的核心。JScrollPane: 一个带滚动条的面板,我们将JTextArea放入JScrollPane中,这样当文本内容超出窗口大小时,就会出现滚动条。JMenuBar: 菜单栏,位于窗口顶部。JMenu: 菜单,如“文件”。JMenuItem: 菜单项,如“新建”、“打开”。
核心方法
createMenuBar(): 负责创建和组装菜单栏及其所有子组件。newFile(): 清空文本区域,并将currentFile设为null,表示当前没有关联的文件。openFile():- 使用
JFileChooser创建一个“打开文件”的对话框。 - 当用户选择文件并点击“打开”后,获取选中的
File对象。 - 使用
BufferedReader和JTextArea的read()方法高效地将文件内容读入文本区域。
- 使用
saveFile()/saveAsFile():saveFile()用于保存已有文件,saveAsFile()用于将文件另存为新位置或新名称。- 同样使用
JFileChooser让用户选择保存位置和文件名。 - 使用
BufferedWriter和JTextArea的write()方法将文本区域的内容写入文件。
exitApp(): 简单地调用System.exit(0)来终止程序。
事件处理
addActionListener(...): 为菜单项添加事件监听器,当用户点击菜单项时,会执行指定的代码(点击“打开”就调用openFile()方法)。addWindowListener(...): 为窗口添加事件监听器,这里我们监听窗口关闭事件,可以在关闭前提示用户保存。
main 方法
SwingUtilities.invokeLater(...): 这是 Swing 编程的一个最佳实践,它确保所有 GUI 的创建和更新都在事件分发线程上执行,避免了多线程操作 GUI 可能导致的线程安全问题。
第四步:编译与运行
- 保存文件: 将上面的代码保存为
NotepadApp.java。 - 打开命令行: 导航到你保存
NotepadApp.java文件的目录。 - 编译代码:
javac NotepadApp.java
如果没有报错,会生成一个
NotepadApp.class文件。 - 运行程序:
java NotepadApp
这时,你应该能看到一个简单的记事本窗口弹出来了。
第五步:进阶与扩展
这个基础的记事本已经具备了核心功能,如果你想让它更完善,可以考虑以下扩展:
- 实现“修改”状态:
JTextArea本身没有“是否被修改”的标志,你需要自己添加一个boolean isModified = false;变量,每当用户在文本区域输入时,通过KeyListener将其设为true,保存后设为false,这样在关闭窗口时就能准确判断。 - 添加更多功能:
- 编辑菜单: 添加“撤销”、“重做”、“剪切”、“复制”、“粘贴”功能,这些功能
JTextArea本身已经提供,通过getActionMap()和getInputMap()可以很方便地绑定到快捷键(如Ctrl+C)。 - 格式菜单: 添加“字体”、“颜色”设置。
- 查找和替换: 添加查找和替换对话框。
- 编辑菜单: 添加“撤销”、“重做”、“剪切”、“复制”、“粘贴”功能,这些功能
- 使用更现代的 GUI 库:
- JavaFX: 这是 Oracle 推荐的下一代 GUI 工具包,功能更强大,界面更现代化,支持 CSS 样式和 FXML 布局文件,如果你有兴趣,可以尝试用 JavaFX 重写这个记事本。
- 打包成可执行文件:
- 使用 IDE(如 IntelliJ IDEA)的 "Build Artifacts" 功能,可以将你的 Swing 应用打包成一个
.jar文件,方便分发。 - 可以进一步使用工具(如 Launch4j)将
.jar文件打包成.exe,这样 Windows 用户就可以直接双击运行了。
- 使用 IDE(如 IntelliJ IDEA)的 "Build Artifacts" 功能,可以将你的 Swing 应用打包成一个
希望这个详细的教程能帮助你成功创建你的第一个 Java 记事本程序!
