文件1:NotepadMain.java - 教程

一、先搞懂:这个文件是干嘛的?

这个文件是整个记事本程序的主窗口 + 总控中心,相当于你打开的记事本软件的 “主界面”:

  • 负责画出记事本的窗口、文本输入区域;
  • 把 “新建 / 保存文件”“复制粘贴”“设置字体” 等功能整合到窗口里;
  • 控制窗口的标题、大小、关闭逻辑(比如关窗口前提示保存)。

二、逐段拆解代码(通俗版)

1. 开头的 “导入语句”—— 搬工具
import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.undo.UndoManager;
  • 类比:你要做记事本,得先从 “Java 工具库” 里把需要的工具搬过来:
    • javax.swing.*/java.awt.*:做窗口、按钮、文本框的 “界面工具”(比如造窗口、造写字的文本框);
    • WindowAdapter/WindowEvent:检测 “窗口关闭” 的 “感应器工具”;
    • UndoManager:实现 “撤销” 功能的 “历史记录工具”(记你做过的操作,能撤回)。
2. 类的定义 —— 给记事本定 “身份”
public class NotepadMain extends JFrame {
  • 通俗解释:
    • public class NotepadMain:给这个程序起个名字叫NotepadMain(主记事本),是 “公开能用” 的;
    • extends JFrame:表示这个程序 “继承” 了 Java 的 “窗口模板”(JFrame),所以它天生就是一个窗口(不用自己从零造窗口)。
3. 成员变量 —— 记事本的 “零件”
// 新增:撤销管理器
public UndoManager undoManager;
// 核心组件
public JTextArea textArea;
public JScrollPane scrollPane;
public String currentFilePath; // 当前打开的文件路径
public boolean isChanged; // 文本是否被修改
// 模块引用
private FileOperations fileOps;
private EditOperations editOps;
private FormatSettings formatSettings;
private UtilityFunctions utility;
  • 类比:这些是记事本的核心零件,每个零件有明确作用:
    变量名通俗含义
    undoManager撤销功能的 “历史记录本”(记你输入 / 删除的内容,点撤销就能回退)
    textArea你写字的 “文本框”(就是记事本里能输入文字的区域)
    scrollPane文本框的 “滚动条”(文字太多时能上下滑)
    currentFilePath记录 “当前打开的文件存在电脑哪个位置”(比如 C 盘 / 桌面 /xxx.txt)
    isChanged标记 “文本有没有改”(改了就标 true,关窗口时提示保存;没改标 false,直接关)
    fileOps关联 “新建 / 保存文件” 功能(比如点 “文件” 菜单的功能都靠它)
    editOps关联 “复制 / 粘贴 / 查找” 功能(点 “编辑” 菜单的功能靠它)
    formatSettings关联 “自动换行 / 设置字体” 功能(点 “格式” 菜单的功能靠它)
    utility关联 “状态栏 / 帮助” 功能(点 “查看 / 帮助” 菜单的功能靠它)
4. 构造方法 —— 组装记事本(核心!)
public NotepadMain() {
    // 初始化文本区域后,添加撤销管理器
    textArea = new JTextArea();
    undoManager = new UndoManager();
    textArea.getDocument().addUndoableEditListener(undoManager); // 绑定文本编辑事件
    // 初始化组件
    textArea = new JTextArea();
    scrollPane = new JScrollPane(textArea);
    currentFilePath = null;
    isChanged = false;
    // 初始化模块
    fileOps = new FileOperations(this);
    editOps = new EditOperations(this);
    formatSettings = new FormatSettings(this);
    utility = new UtilityFunctions(this);
    // 窗口设置
    setTitle("记事本");
    setSize(800, 600);
    setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // 自定义关闭逻辑
    addWindowListener(new WindowAdapter() {
        @Override
        public void windowClosing(WindowEvent e) {
            fileOps.exit(); // 关闭前检查保存
        }
    });
    // 组装界面
    setJMenuBar(createMenuBar()); // 添加菜单栏
    add(scrollPane, BorderLayout.CENTER); // 添加文本区域
    add(utility.createStatusBar(), BorderLayout.SOUTH); // 添加状态栏
    // 监听文本变化
    textArea.getDocument().addDocumentListener(new javax.swing.event.DocumentListener() {
        @Override
        public void insertUpdate(javax.swing.event.DocumentEvent e) {
            isChanged = true;
            updateTitle();
        }
        @Override
        public void removeUpdate(javax.swing.event.DocumentEvent e) {
            isChanged = true;
            updateTitle();
        }
        @Override
        public void changedUpdate(javax.swing.event.DocumentEvent e) {}
    });
}
  • 通俗解释:这是 “组装记事本” 的过程,一步一步做:
第一步:造文本框 + 绑定撤销功能
textArea = new JTextArea(); // 造一个空白的文本框
undoManager = new UndoManager(); // 造一个“撤销记录本”
textArea.getDocument().addUndoableEditListener(undoManager); // 给文本框装“感应器”:你每输入/删除一个字,都记到撤销记录本里
// (小提醒:代码里重复写了textArea = new JTextArea();,可以删掉下面那行,不影响功能但更整洁)
scrollPane = new JScrollPane(textArea); // 给文本框加滚动条
currentFilePath = null; // 初始时没打开任何文件,路径记为“空”
isChanged = false; // 初始时文本没修改,标记为“false”
第二步:加载所有功能模块
fileOps = new FileOperations(this); // 加载“文件功能”(新建/保存)
editOps = new EditOperations(this); // 加载“编辑功能”(复制/粘贴)
formatSettings = new FormatSettings(this); // 加载“格式功能”(字体/换行)
utility = new UtilityFunctions(this); // 加载“辅助功能”(状态栏/帮助)
// 这里的“this”表示“把主窗口传给这些功能”,比如保存文件后要更新窗口标题,功能模块能找到主窗口
第三步:设置窗口的基础属性
setTitle("记事本"); // 窗口标题写“记事本”
setSize(800, 600); // 窗口大小:宽800像素,高600像素
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // 关窗口时不直接关(要先检查保存)
// 给窗口装“关闭感应器”:点叉号关闭时,先执行fileOps.exit()(检查是否保存)
addWindowListener(new WindowAdapter() {
    @Override
    public void windowClosing(WindowEvent e) {
        fileOps.exit(); // 关窗口前,先调用“文件功能”的“退出”方法(检查保存)
    }
});
第四步:把菜单、文本框、状态栏拼到窗口里
setJMenuBar(createMenuBar()); // 给窗口加菜单栏(比如“文件/编辑/格式”这些菜单)
add(scrollPane, BorderLayout.CENTER); // 把带滚动条的文本框放在窗口正中间
add(utility.createStatusBar(), BorderLayout.SOUTH); // 把状态栏放在窗口最下方(显示行号/字符数)
第五步:给文本框装 “修改感应器”
textArea.getDocument().addDocumentListener(...) {
    // 当你“输入文字”时(insertUpdate):
    public void insertUpdate(...) {
        isChanged = true; // 标记“文本改了”
        updateTitle(); // 更新窗口标题(加个*号提示修改)
    }
    // 当你“删除文字”时(removeUpdate):
    public void removeUpdate(...) {
        isChanged = true; // 标记“文本改了”
        updateTitle(); // 更新窗口标题(加*号)
    }
    // changedUpdate:暂时不用(针对样式修改,比如字体,这里忽略)
}
5. createMenuBar 方法 —— 造菜单栏
private JMenuBar createMenuBar() {
    JMenuBar menuBar = new JMenuBar();
    // 添加各模块的菜单
    menuBar.add(fileOps.createFileMenu()); // 加“文件”菜单
    menuBar.add(editOps.createEditMenu()); // 加“编辑”菜单
    menuBar.add(formatSettings.createFormatMenu()); // 加“格式”菜单
    menuBar.add(utility.createViewMenu()); // 加“查看”菜单
    menuBar.add(utility.createHelpMenu()); // 加“帮助”菜单
    return menuBar;
}
  • 通俗解释:造一个空的菜单栏,然后把 “文件 / 编辑 / 格式 / 查看 / 帮助” 这些菜单一个个加进去(每个菜单的具体按钮,比如 “新建”“保存”,是在各自的功能模块里定义的)。
6. updateTitle 方法 —— 更新窗口标题
public void updateTitle() {
    String title = "记事本";
    if (currentFilePath != null) {
        title = new java.io.File(currentFilePath).getName(); // 有打开的文件,标题显示文件名
    }
    if (isChanged) {
        title += " *"; // 文本改了,标题加个*号(比如“笔记.txt *”)
    }
    setTitle(title);
}
  • 通俗解释:
    • 没打开文件时,标题是 “记事本”;
    • 打开了文件(比如 “笔记.txt”),标题显示 “笔记.txt”;
    • 文本改了没保存,标题变成 “笔记.txt *”(提醒你有修改)。
7. main 方法 —— 启动记事本(程序入口)
public static void main(String[] args) {
    // 确保在EDT线程中运行Swing组件(不用懂,固定写法:保证界面不卡)
    SwingUtilities.invokeLater(() -> {
        new NotepadMain().setVisible(true); // 造一个记事本窗口,并且显示出来
    });
}
  • 通俗解释:这是程序的 “启动开关”—— 运行这个代码,就会执行new NotepadMain()(组装记事本),然后setVisible(true)(把记事本窗口显示在屏幕上)。

三、整体运行逻辑(一句话总结)

  1. 运行程序→触发main方法→组装记事本窗口(造文本框、加载所有功能、装菜单 / 状态栏);
  2. 你操作记事本时(输入文字 / 点菜单):
    • 输入文字→文本框的 “修改感应器” 触发→标题加 * 号;
    • 点 “文件→保存”→fileOps模块执行保存→isChanged变回 false→标题去掉 * 号;
    • 点窗口叉号→“关闭感应器” 触发→fileOps检查是否有修改→没修改直接关,有修改提示保存;
    • 点 “编辑→撤销”→undoManager撤回上一步操作

总代码:

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.undo.UndoManager; // 顶部导入
public class NotepadMain extends JFrame {
    // 新增:撤销管理器
    public UndoManager undoManager;
    // 核心组件
    public JTextArea textArea;
    public JScrollPane scrollPane;
    public String currentFilePath; // 当前打开的文件路径
    public boolean isChanged; // 文本是否被修改
    // 模块引用
    private FileOperations fileOps;
    private EditOperations editOps;
    private FormatSettings formatSettings;
    private UtilityFunctions utility;
    public NotepadMain() {
        // 初始化文本区域后,添加撤销管理器
        textArea = new JTextArea();
        undoManager = new UndoManager();
        textArea.getDocument().addUndoableEditListener(undoManager); // 绑定文本编辑事件
        // 初始化组件
        textArea = new JTextArea();
        scrollPane = new JScrollPane(textArea);
        currentFilePath = null;
        isChanged = false;
        // 初始化模块
        fileOps = new FileOperations(this);
        editOps = new EditOperations(this);
        formatSettings = new FormatSettings(this);
        utility = new UtilityFunctions(this);
        // 窗口设置
        setTitle("记事本");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); // 自定义关闭逻辑
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                fileOps.exit(); // 关闭前检查保存
            }
        });
        // 组装界面
        setJMenuBar(createMenuBar()); // 添加菜单栏
        add(scrollPane, BorderLayout.CENTER); // 添加文本区域
        add(utility.createStatusBar(), BorderLayout.SOUTH); // 添加状态栏
        // 监听文本变化
        textArea.getDocument().addDocumentListener(new javax.swing.event.DocumentListener() {
            @Override
            public void insertUpdate(javax.swing.event.DocumentEvent e) {
                isChanged = true;
                updateTitle();
            }
            @Override
            public void removeUpdate(javax.swing.event.DocumentEvent e) {
                isChanged = true;
                updateTitle();
            }
            @Override
            public void changedUpdate(javax.swing.event.DocumentEvent e) {}
        });
    }
    // 创建菜单栏
    private JMenuBar createMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        // 添加各模块的菜单
        menuBar.add(fileOps.createFileMenu());
        menuBar.add(editOps.createEditMenu());
        menuBar.add(formatSettings.createFormatMenu());
        menuBar.add(utility.createViewMenu());
        menuBar.add(utility.createHelpMenu());
        return menuBar;
    }
    // 更新窗口标题(显示文件名和修改状态)
    public void updateTitle() {
        String title = "记事本";
        if (currentFilePath != null) {
            title = new java.io.File(currentFilePath).getName();
        }
        if (isChanged) {
            title += " *"; // 有修改时加星号
        }
        setTitle(title);
    }
    public static void main(String[] args) {
        // 确保在EDT线程中运行Swing组件
        SwingUtilities.invokeLater(() -> {
            new NotepadMain().setVisible(true);
        });
    }
}

posted on 2026-01-02 14:07  ljbguanli  阅读(0)  评论(0)    收藏  举报