欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 焦点 > QT记事本

QT记事本

2025/4/1 7:25:22 来源:https://blog.csdn.net/weixin_69851948/article/details/146518935  浏览:    关键词:QT记事本

记事本应用程序提供了基本的文本编辑功能,支持文件的新建、打开、保存和另存为操作,同时具备修改提示和关闭窗口时的保存确认功能。使用 UTF - 8 编码确保了对多语言文本的支持。
在这里插入图片描述

1. 项目整体结构

  • main.cpp:程序的入口点,负责初始化 Qt 应用程序并创建Notepad窗口实例,最后进入应用程序的事件循环。
  • mainwindow.h:定义了Notepad类,继承自QMainWindow,包含了窗口的成员变量和成员函数的声明。
  • mainwindow.cpp:实现了Notepad类的成员函数,完成了记事本的各种功能。

2. 主要功能模块

2.1 窗口初始化
  • Notepad类的构造函数中,创建了一个QTextEdit控件作为中央部件,用于文本编辑。
  • 调用createActions()createMenus()函数创建菜单栏和菜单项对应的动作。
  • 设置窗口标题、大小和初始修改状态。
2.2 菜单栏和动作
  • 文件菜单 (文件(&F))
    • 新建 (&N) (Ctrl+N):调用newFile()函数,在保存当前修改后清空文本编辑区,重置当前文件名和修改状态。
    • 打开 (&O)… (Ctrl+O):调用openFile()函数,在保存当前修改后弹出文件选择对话框,选择文件并加载到文本编辑区。
    • 保存 (&S) (Ctrl+S):调用saveFile()函数,如果当前文件名为空,则调用saveAsFile()函数进行另存为操作;否则直接保存当前文件。
    • 另存为 (&A)… (Ctrl+Shift+S):调用saveAsFile()函数,弹出文件保存对话框,选择保存路径和文件名并保存文件。
    • 退出 (&X):调用QWidget::close()函数关闭窗口。
  • 帮助菜单 (帮助(&H))
    • 关于 (&A)…:调用about()函数,弹出关于对话框,显示应用程序的版本信息和开发环境。
2.3 文件操作
  • 保存文件 (save(const QString &fileName)):使用QSaveFile打开文件,以 UTF - 8 编码将文本编辑区的内容写入文件。如果保存成功,更新当前文件名和修改状态。
  • 加载文件 (loadFile(const QString &fileName)):使用QFile打开文件,自动检测文件编码并读取内容到文本编辑区。如果打开失败,弹出错误对话框。
2.4 修改提示
  • maybeSave():在新建文件、打开文件或关闭窗口时,检查文本编辑区的内容是否被修改。如果已修改,弹出警告对话框询问用户是否保存更改,根据用户的选择进行相应操作。
2.5 关闭窗口处理
  • closeEvent(QCloseEvent \*event):在窗口关闭时,调用maybeSave()函数询问用户是否保存更改。如果保存成功或用户选择不保存,则接受关闭事件;否则忽略关闭事件。

main.c

// main.cpp
#include "mainwindow.h"
#include <QApplication>int main(int argc ,char *argv[])
{QApplication app(argc, argv);app.setWindowIcon(QIcon(":/icons/notepad.png"));Notepad notepad;notepad.show();return app.exec();
}

mianwidow.c

// notepad.cpp
#include "mainwindow.h"
#include <QTextStream>
#include <QSaveFile>       // 添加缺失的头文件
#include <QStringConverter> // 添加缺失的头文件#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endifNotepad::Notepad(QWidget *parent): QMainWindow(parent),textEdit(new QTextEdit),fileMenu(nullptr),newAct(nullptr),openAct(nullptr),saveAct(nullptr),saveAsAct(nullptr),exitAct(nullptr),helpMenu(nullptr),aboutAct(nullptr)
{textEdit = new QTextEdit;setCentralWidget(textEdit);createActions();createMenus();setWindowTitle(QStringLiteral("Qt记事本[*]"));resize(800, 600);setWindowModified(false);
}void Notepad::createActions()
{newAct = new QAction(QStringLiteral("新建(&N)"), this);newAct->setShortcut(QKeySequence::New);connect(newAct, &QAction::triggered, this, &Notepad::newFile);openAct = new QAction(QStringLiteral("打开(&O)..."), this);openAct->setShortcut(QKeySequence::Open);connect(openAct, &QAction::triggered, this, &Notepad::openFile);saveAct = new QAction(QStringLiteral("保存(&S)"), this);saveAct->setShortcut(QKeySequence::Save);connect(saveAct, &QAction::triggered, this, &Notepad::saveFile);saveAsAct = new QAction(QStringLiteral("另存为(&A)..."), this);saveAsAct->setShortcut(QKeySequence::SaveAs);connect(saveAsAct, &QAction::triggered, this, &Notepad::saveAsFile);exitAct = new QAction(QStringLiteral("退出(&X)"), this);connect(exitAct, &QAction::triggered, this, &QWidget::close);aboutAct = new QAction(QStringLiteral("关于(&A)..."), this);connect(aboutAct, &QAction::triggered, this, &Notepad::about);
}void Notepad::createMenus()
{fileMenu = menuBar()->addMenu(QStringLiteral("文件(&F)"));fileMenu->addAction(newAct);fileMenu->addAction(openAct);fileMenu->addAction(saveAct);fileMenu->addAction(saveAsAct);fileMenu->addSeparator();fileMenu->addAction(exitAct);helpMenu = menuBar()->addMenu(QStringLiteral("帮助(&H)"));helpMenu->addAction(aboutAct);
}void Notepad::newFile()
{if (maybeSave()) {textEdit->clear();currentFile.clear();setWindowModified(false);}
}void Notepad::openFile()
{if (maybeSave()) {QString fileName = QFileDialog::getOpenFileName(this);if (!fileName.isEmpty()) {loadFile(fileName);setWindowModified(false);}}
}bool Notepad::saveFile()
{return currentFile.isEmpty() ? saveAsFile() : save(currentFile);
}bool Notepad::saveAsFile()  // 修正返回类型为bool
{QString fileName = QFileDialog::getSaveFileName(this,QStringLiteral("另存为"), currentFile);return fileName.isEmpty() ? false : save(fileName);
}
void Notepad::about()
{QMessageBox::about(this, QStringLiteral("关于 Qt记事本"),QStringLiteral("<h2>Qt记事本 2.0</h2>""<p>基于Qt 6.5开发</p>""<p>支持UTF-8编码文件读写</p>"));
}bool Notepad::maybeSave()
{if (!textEdit->document()->isModified())return true;QMessageBox::StandardButton ret = QMessageBox::warning(this,QStringLiteral("文档修改"),QStringLiteral("文档内容已修改,是否保存更改?"),QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);if (ret == QMessageBox::Save)return saveFile();else if (ret == QMessageBox::Cancel)return false;return true;
}bool Notepad::save(const QString &fileName)
{QSaveFile file(fileName);if (file.open(QFile::WriteOnly | QFile::Text)) {QTextStream out(&file);out.setEncoding(QStringConverter::Utf8);out << textEdit->toPlainText();if (file.commit()) {currentFile = fileName;setWindowModified(false);return true;}}QMessageBox::critical(this, QStringLiteral("保存失败"),QStringLiteral("无法保存文件:\n%1\n%2").arg(fileName, file.errorString()));return false;
}void Notepad::loadFile(const QString &fileName)
{QFile file(fileName);if (file.open(QFile::ReadOnly | QFile::Text)) {QTextStream in(&file);in.setAutoDetectUnicode(true);textEdit->setText(in.readAll());currentFile = fileName;} else {QMessageBox::critical(this, QStringLiteral("打开失败"),QStringLiteral("无法打开文件:\n%1\n%2").arg(fileName, file.errorString()));}
}void Notepad::closeEvent(QCloseEvent *event)
{maybeSave() ? event->accept() : event->ignore();
}Notepad::~Notepad() {}

一、核心功能实现分析

  1. 文件操作框架

    • 采用

      QSaveFile
      

      实现原子写入(先写临时文件再替换原文件),有效防止写入中断导致文件损坏;

    • loadFile()
      

      使用

      QTextStream
      

      自动检测编码,但建议增加手动编码选择功能(参考Notepad++的多编码支持);

    • 缺少最近文件列表功能,可参考Notepad++的Session机制

      实现历史文件恢复。

  2. 菜单系统架构

    • 采用经典MVC模式,通过QAction实现命令与UI解耦;
    • 快捷键绑定符合平台规范,但缺少自定义快捷键功能(Notepad++支持快捷键自定义)。
  3. 编码处理

    • 显式设置UTF-8编码(QStringConverter::Utf8),但未处理BOM标记;
    • 建议参考Notepad++的编码识别机制,添加自动检测编码功能。

二、潜在问题及改进建议

  1. 大文件处理

    • 当前实现直接读取整个文件到内存,存在内存耗尽风险。建议:

      复制

      // 分块读取(示例)
      while(!in.atEnd()) {QString chunk = in.read(4096);textEdit->insertPlainText(chunk);
      }
      
    • 可参考Notepad++的1MB缓存限制机制

  2. 安全漏洞预防

    • 未实现文件变更监控,建议添加QFileSystemWatcher检测外部修改;

    • 需注意Notepad++曾出现的编码转换漏洞

      ,建议对转换缓冲区进行边界检查。

  3. 用户体验优化

    • 增加多文档支持(参考Notepad++的Tab系统)

    • 实现撤销/重做栈:

      复制

      connect(textEdit->document(), &QTextDocument::undoAvailable, undoAct, &QAction::setEnabled);
      

三、关键代码段优化

  1. 编码处理增强

    复制

    // 改进后的保存函数
    bool Notepad::save(const QString &fileName) {QSaveFile file(fileName);if (file.open(QFile::WriteOnly | QFile::Text)) {QTextStream out(&file);// 添加BOM支持out.setGenerateByteOrderMark(true); out.setEncoding(QStringConverter::Utf8);// 分块写入const QString text = textEdit->toPlainText();for(int i=0; i<text.size(); i+=4096) {out << text.mid(i, 4096);}return file.commit();}//...错误处理
    }
    
  2. 会话管理实现

    // 参考Notepad++的Session结构[4](@ref)
    struct Session {QStringList recentFiles;QMap<QString, QByteArray> fileStates; // 文件路径+光标位置等
    };
    

四、架构扩展建议

  1. 插件系统设计

    • 创建PluginInterface抽象基类
    • 实现类似Notepad++的插件加载机制
  2. 语法高亮支持

    // 参考Scintilla库集成[2](@ref)
    class SyntaxHighlighter : public QSyntaxHighlighter {// 实现词法分析规则
    };
    

mianwindow.h

// notepad.h
#ifndef NOTEPAD_H
#define NOTEPAD_H#include <QMainWindow>
#include <QTextEdit>
#include <QFileDialog>
#include <QMessageBox>
#include <QCloseEvent>
#include <QTextStream>
#include <QMenuBar>       // 添加缺失的头文件
#include <QMenu>          // 添加缺失的头文件
#include <QAction>        // 添加缺失的头文件class Notepad : public QMainWindow
{Q_OBJECTpublic:explicit Notepad(QWidget *parent = nullptr);~Notepad();protected:void closeEvent(QCloseEvent *event) override;private slots:void newFile();void openFile();bool saveFile();       // 修正返回类型为boolbool saveAsFile();     // 修正返回类型为boolvoid about();private:void createActions();void createMenus();bool maybeSave();bool save(const QString &fileName);void loadFile(const QString &fileName);QTextEdit *textEdit;QString currentFile;QMenu *fileMenu;QAction *newAct;QAction *openAct;QAction *saveAct;QAction *saveAsAct;QAction *exitAct;QMenu *helpMenu;QAction *aboutAct;
};#endif // NOTEPAD_H

一、代码结构分析

  1. 继承关系

    cpp

    复制

    class Notepad : public QMainWindow
    
    • 符合Qt主窗口程序标准结构
    • 支持菜单栏、工具栏等标准组件
  2. 成员变量设计

    cpp

    复制

    QTextEdit *textEdit;       // 核心编辑组件
    QString currentFile;       // 当前文件路径
    QMenu *fileMenu, *helpMenu; // 主菜单项
    QAction *newAct, *openAct... // 功能动作
    
    • 采用Qt对象树内存管理机制
    • 指针初始化为nullptr(构造函数初始化列表可见)

二、接口设计评估

  1. 信号槽系统

    cpp

    复制

    private slots:void newFile();bool saveFile();  // 注意:Qt槽函数通常返回void
    
    • 存在设计矛盾:saveFile()返回bool但作为槽函数

    建议修改

    cpp

    复制

    private:bool performSave(); // 非槽函数
    private slots:void saveFile();    // 调用performSave()
    
  2. 事件处理

    cpp

    复制

    protected:void closeEvent(QCloseEvent *event) override;
    
    • 正确覆盖基类虚函数
    • 配合maybeSave()实现关闭确认

三、代码健壮性分析

  1. 头文件包含

    cpp

    复制

    #include <QMenuBar>  // 冗余包含
    
    • QMainWindow已包含QMenuBar

    优化建议

    cpp

    复制

    // 前置声明替代部分包含
    class QMenu;
    class QAction;
    
  2. 防御性编程

    cpp

    复制

    void createActions(); // 未处理可能的创建失败
    

    建议增强

    cpp

    复制

    bool createActions(); // 返回创建状态
    

四、扩展性改进建议

  1. 支持多编码

    cpp

    复制

    // 添加编码相关成员
    QTextCodec *currentCodec = QTextCodec::codecForName("UTF-8");
    
  2. 会话管理

    cpp

    复制

    // 添加最近文件列表
    QStringList recentFiles;
    static const int MAX_RECENT_FILES = 5;
    

五、代码规范优化

  1. 命名一致性

    cpp

    复制

    void about();  // 与"关于Qt"的常规命名不一致
    
    • 建议改为aboutQtNotepad()
  2. const正确性

    cpp

    复制

    bool save(const QString &fileName); 
    
    • 可添加const修饰:

      cpp

      复制

      bool isModified() const;
      

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词