QT 学习及实操 - QFile 实现记事本功能

11490DX Re: Master Lv.15

文中知识点包含 QFile 文件处理、点击按钮弹出子窗口、设置快捷键等。

介绍 - 文件处理相关

在介绍 QFile 之前,先介绍 QByteArray。QByteArray 是字节数组,一种数据结构,存储一堆字符,相当于是 const char *。字节数组的最后一般会有一个 '\0'。但是不用你自己加,当你 QByteArray ba = "maimai"; 的时候,自己会自动在最后添加一个 \0

  • 在 QByteArray 后加另一个字符串:ba.append(x);
  • QByteArray 转 QString:QString(ba);

QFile 不用 #include <QFile>,因为我没加然后编译过了。

QFile 可以对文件进行读写处理。有没有想到打代码的时候最开始写的 freopen

  • 声明变量并且赋上文件的精确位置:QFile file(QString filePath);
  • 打开这个文件:file.open(mode); 这个 mode 指的是你打开这个文件的方式。比如 QIODevice::ReadOnly 代表只读、QIODevice::WriteOnly 为只写等。
  • 关闭这个文件:file.close();
  • 读取整个文件内容:QByteArray ba = file.readAll();
  • 写入文件内容:file.write(QByteArray ba);

  • 呼出一个资源管理器来选择某个文件并且返回该文件精确位置:QString filePath = QFileDialog::getOpenFileName(*parent, "Title", QString start_Dir, QString FILETYPE); 其中若选中文件了则返回精确位置,否则返回空串。

    start_Dir 代表这个资源管理器最开始所在的位置,FILETYPE 为可以选择的文件后缀名,比如 "文本文档 (*.txt);;C++ 源文件 (*.cpp);;Python 源文件 (*.py)",其中 ;; 代表分隔两种不同类型,括号里面的种类可以为 (*.*),即所有文件。

  • 呼出一个资源管理器来设置某个文件的保存位置并且返回该文件精确位置:QString filePath = QFileDialog::getSaveFileName(*parent, "Title", start_Dir, FILETYPE)

  • 获取某个精确位置的文件的文件信息:QFileInfo fileinfo = QFileInfo(filePath); 然后就可以通过 fileinfo.xxx 来访问这个文件的信息了。

介绍 - MainWindow 类

不同于 Widget 类,MainWindow 类 拥有一个菜单栏,也就是类似【文件(F) 编辑(E)】之类的菜单。可以在设计界面更改这些菜单。

对于每一个菜单里面的每一个元素,类型都是 QAction。点击一个 QAction 发出的信号就是 QAction::triggered()。因为对于 QAction 它在设计界面没有【转到槽】的选项,所以只能使用 connect 方法来 连接信号与槽。

介绍 - 其它

TextEdit

  • 获取某个 TextEdit 中内容:textEdit->toPlainText()

  • 设置这个 TextEdit 字体:textEdit->setFont(QFont font);

  • 复制选中内容到剪贴板:textEdit->copy();

  • 粘贴选中内容到剪贴板:textEdit->paste();

  • 撤回:textEdit->undo();

  • 撤销撤回:textEdit->redo();

  • 对于其内容有改变就会发出信号的槽函数:void ClassName::on_textEdit_textChanged();

  • 访问当前光标所在行号和列号:

    1
    2
    3
    QTextCursor cursor = ui->textEdit->textCursor();
    int y = cursor.blockNumber()+1, x = cursor.columnNumber()+1;
    ui->positionDisplay->setText("行 "+QString::number(y)+",列 "+QString::number(x));
  • 设置自动换行:ui->textEdit->setWordWrapMode(mode);

    mode 的几种可能取值:

    • QTextOption::NoWrap:不自动换行
    • QTextOption::WrapAnywhere:自动换行,可能在一个单词中间的任意位置换行
    • QTextOption::WordWrap:在单词边界处自动换行

QFont

  • 呼出字体设置框设置字体,返回设置出的字体属性:QFont font = QFontDialog::getfont(&ok, *parent); 这个 &ok 返回是否修改成功。若点取消则返回 false

QMessageBox

  • 呼出问题窗口并且显示三个按钮:int res = QMessageBox::question(*parent, "Title", "Question String", button1, button2, button3); 返回一个 int 代表你按的是哪个按钮,每一个 button 都是 QMessageBox::YesQMessageBox::No 之类的按钮。
  • 判断最终按的是是否为某个按钮:if(res == QMessageBox::Yes){...}

QShortcut

  • 创建一个新快捷键组合:QShortcut *newshortcut = new QShortcut(QKeySequence("ctrl+n"), *parent);
  • 连接这个快捷键组合和某个槽:connect(newShortcut, &QShortcut::activated, *receiver, *method);

新跳出一个窗口

右击该工程文件夹,点击【Add new…】或【添加新文件…】。

然后选择 Qt -> Qt 设计师界面类。之后选择你需要的类再取个类名就可以了。我们定原来的主窗口类名为 mainwindow,新窗口类名为 newwindow

mainwindow.cpp 里面 #include "newwindow.h",然后设置一个全局变量为 newwindow *cur;

每一次要打开另一个窗口的时候就 cur->show();,关闭就 cur->close();

由于我实在想不到有什么方法可以检测这个窗口是否存在,所以每一次点击那个按钮的时候,我就先关一次再开一次,这样就可以保证只有一个子窗口。

点击关闭按钮的时候询问

mainwindow.h

1
2
3
4
5
#include <QCloseEvent>
...
private slots:
...
void closeEvent(QCloseEvent *event);

mainwindow.cpp

1
2
3
4
5
6
void MainWindow::closeEvent(QCloseEvent *event){
int res = QMessageBox::question(this, "Title", "确认是否退出?", QMessageBox::Yes, QMessageBox::No);
if(res == QMessageBox::Yes){
event->accept();
}else event->ignore();
}

MaiPad 记事本程序设计

UI

逻辑部分

【文件】部分有下面四个功能【新建】【打开】【保存】【另存为】。我在这里设置了三个全局 bool 变量,isnewfile 代表这个文件是否有它的精确路径(若没有为 1),isstarted 代表现在是否已经打开了一个文件,issaved 代表这个文件目前是否被保存。

以及一个 QString 全局变量代表目前文件的精确路径(isnewfile == 1 这玩意不管),一个 int 变量存储现在是第几个新建文件,和一个 QFileInfo 存储现在文件的信息。

  • 对于【新建】,需要检查之前是否有内容或者之前的内容是否保存。为了简化,我们设 issaved 初始值为 1。若没保存,就问用户要不要保存。成功保存了之后就新建文件,重置三个 bool 变量的名字,并且让这个 int 变量自增。
  • 对于【打开】,还是检查之前的内容是否保存。然后还是一样的。成功保存了之后就打开文件,更新精确路径和文件信息。
  • 对于【保存】,就检查是否有精确路径。若无,创建一个。否则基于那个精确路径保存。
  • 对于【另存为】,就直接创建一个精确路径来基于其保存。
  • 并且如果中间的文本框的值改了,那么修改标题栏,将其加一个 * 代表该文件未保存。
  • 如果鼠标指针改了,那么更改行号和列号。
  • 最后加一个帮助 -> 关于本“MaiPad”跳转至我的第二个窗口,以及关闭之前若未保存询问用户是否保存即可。

这次由于流畅度原因,没有加 Unifont 字体,但是依然加了 Saira 和 Monocraft 字体。

后记

这次写的是真的比较大了。从中午一直写到现在(是不是都没有之前那个计算器的大)。

因为自动换行不常用,所以就没有设置快捷键。

现在已经 6:50 了,我又该走了。

希望明天的 7 月份的最后一次学习能够搞个大点的出来,但是教练恐怕不允许 qwq

工程源文件 最终程序

  • Title: QT 学习及实操 - QFile 实现记事本功能
  • Author: 11490DX
  • Created at : 2025-07-30 16:33:17
  • Updated at : 2025-07-30 18:49:29
  • Link: https://11490dx.net/2025/07/30/QT-R70730/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments