5 实现文件打开功能
5.1 开发流程
- 为QPushButton对应Open的控件设置槽函数
- 槽函数代码开发
- 打开文件
- 读取文件
- 把文件数据显示在TextEdit控件上
5.2 代码实现
先选择打开按键,选择点击信号与槽的连接,然后通过代码实现开发流程。

cpp
void Widget::on_btnSave_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
"D:/AAA",
tr("Text(*.txt)"));
ui->textEdit->clear();
QFile file;
file.setFileName(fileName);
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
qDebug() << "file open error";
}
QTextStream in(&file);
in.setCodec("UTF-8");
while(!in.atEnd()){
QString context = in.readLine();
//qDebug() << context; 显示在应用程序输出,而不是界面
//ui -> textEdit -> setText(context); 显示不完整
ui->textEdit->append(context);
}
file.close();
}
5.3 打开功能优化
存在问题:字符编码设置
如果按之前代码的功能设置为UTF-8的编码,那么在打开ANSI编码的文件时会出现乱码现象,所以我们不应该像之前那样单一设置,后续内容改正。
UTF-8编码设置:
cpp
QTextStream stream(&file);
stream.setCodec("UTF-8");
UTF-16编码设置:
cpp
stream.setCodec("UTF-16");
ANSI编码设置:
cpp
stream.setCodec("ANSI");
5.4 QComboBox
QComboBox 功能概述
QComboBox 是 Qt 框架中用于创建下拉列表的控件,支持用户从一组选项中选择一个值,并可配置为可编辑模式。

主要功能及对应 API
| 功能 | 描述 | API 方法 |
|---|---|---|
| 添加选项 | 向下拉列表添加单个或多个选项 | addItem()、addItems() |
| 获取选项 | 获取当前选中的文本或索引 | currentText()、currentIndex() |
| 设置选项 | 设置当前选中的项 | setCurrentIndex(int) |
| 移除选项 | 从下拉列表中移除项 | removeItem(int) |
| 信号 | 当选项改变时触发的事件 | currentIndexChanged(int) |
| 可编辑性 | 设置下拉列表是否可编辑 | setEditable(bool) |
| 自定义数据 | 向下拉列表项关联额外的数据 | setItemData(int, const QVariant&) |
| 清空列表 | 移除所有选项 | clear() |
示例代码
cpp
#include <QComboBox>
#include <QVBoxLayout>
#include <QWidget>
//这个示例展示了 QComboBox 的基本用法,
//包括添加选项、设置为可编辑以及连接信号和槽。
class ComboBoxDemo : public QWidget {
Q_OBJECT
public:
ComboBoxDemo() {
QComboBox *comboBox = new QComboBox(this);
comboBox->addItems({"选项1", "选项2", "选项3"});
comboBox->setEditable(true);
connect(comboBox, SIGNAL(currentIndexChanged(int)),
this, SLOT(onSelectionChanged(int)));
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(comboBox);
}
private slots:
void onSelectionChanged(int index) {
}
};
5.5 记事本支持字符编码
文件打开与编码处理实现
cpp
void Widget::on_btnFileOpen_clicked()
{
// 使用文件对话框获取要打开的文件的路径
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
"D:/AAA/",
tr("Text (*.txt)"));
// 清空文本编辑器的内容
ui->textEdit->clear();
// 设置 QFile 对象的文件名
file.setFileName(fileName);
// 尝试以只读和文本模式打开文件
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
// 如果文件打开失败,输出错误信息
qDebug() << "file open error";
}
// 创建 QTextStream 用于读取文件内容
QTextStream in(&file);
// 从下拉框获取当前选中的字符编码
QString str = ui->comboBox->currentText();
// 将 QString 转化为 char* 类型
const char* c_str = str.toStdString().c_str();
// 设置 QTextStream 的字符编码
in.setCodec(c_str);
// 循环读取文件直到结束
while(!in.atEnd()){
// 读取文件的一行
QString context = in.readLine();
// 将读取的内容追加到文本编辑器
ui->textEdit->append(context);
}
}
注意事项
- 确保
file是类成员变量(类型为QFile) ui->textEdit需要是项目中的QTextEdit组件ui->comboBox应预先填充支持的编码选项(如"UTF-8"、"GBK"等)- 获取用户在
QComboBox上选择的字符编码,用特定编码打开文件,这里注意QComboBox返回QString类型,setCodec参数要求const char*型QString先转成C++的String,再转换成const char *。
支持打开文件后进行字符编码的重新选择和显示加载
cpp
void Widget::onCurrentIndexChanged(int index)
{
// 输出调试信息,表示此槽函数被触发
qDebug() << "currentIndexChanged Signal";
// 清空文本编辑器的内容
ui->textEdit->clear();
// 检查文件是否已经打开
if(file.isOpen()){
// 输出调试信息,表示文件是打开状态
qDebug() << "file is Open";
// 创建 QTextStream 用于读取文件内容
QTextStream in(&file);
// 设置 QTextStream 的字符编码为 QComboBox 当前选中的编码
in.setCodec(ui->comboBox->currentText().toStdString().c_str());
// 将文件指针移动到文件开始位置
file.seek(0);
// 循环读取文件直到文件结束
while(!in.atEnd()){
// 读取文件的一行
QString context = in.readLine();
// 将读取的内容追加到文本编辑器
ui->textEdit->append(context);
}
}
}
5.6 添加行列显示
使用QTextEdit的cursorPositionChanged信号,当光标发生移动时候刷新显示
构造函数连接信号与槽
cpp
// 在Widget构造函数中添加
connect(ui->textEdit,SIGNAL(cursorPositionChanged()),
this,SLOT(oncursorPositionChanged()));
槽函数实现
cpp
void Widget::onCursorPositionChanged()
{
QTextCursor cursor = ui->textEdit->textCursor();
//qDebug() << cursor.blockNumber()+1 <<","<< cursor.columnNumber() + 1;
QString blockNum = QString::number(cursor.blockNumber()+1);
QString columnNum = QString::number(cursor.columnNumber()+1);
const QString labelMes = "L:"+blockNum+",C:"+columnNum+" ";
//const QString labelMes = "行:"+blockNum+",列:"+columnNum+" ";
ui->labelPosition->setText(labelMes);
}
注意事项
comboBox需要预先填充编码选项(如"UTF-8"、"GBK"等)labelPosition需要是界面上的QLabel对象
5.7 添加文件打开提示
目标:比如在打开文件名为"123.txt"时,记事本标题同步此名称。
cpp
this->setWindowTitle(fileName + "- MyNoteBook");
将此代码添加到打开文件,保存文件,关闭文件中,完成目标功能。
5.8 设置当前行高亮
5.8.1 QList
QList 基本用法
包含头文件
cpp
#include <QList>
创建 QList 实例
cpp
QList<int> list;
添加元素
cpp
list.append(1);
list.append(2);
list.append(3);
访问元素
cpp
int firstElement = list[0];
int secondElement = list.at(1);
遍历列表
cpp
// 使用索引遍历
for(int i = 0; i < list.size(); ++i) {
qDebug() << list[i];
}
// 使用范围基的 for 循环
for(int item : list) {
qDebug() << item;
}
移除元素
cpp
list.removeAt(1); // 移除索引为 1 的元素
list.removeOne(3); // 移除一个值为 3 的元素
list.clear(); // 清空整个列表
QList 内部工作原理
-
数组式存储
使用连续内存存储元素,支持快速索引访问(
[]或at())和高效迭代。 -
动态调整大小
自动管理内存分配,支持动态增长和缩减。
-
链表特性
支持在列表首尾高效添加或移除元素(如
append、prepend)。 -
隐式共享(写时复制)
复制时共享内存,仅在修改时进行实际复制,提升性能。
适用场景
- 需要频繁随机访问(通过索引)的场景。
- 主要操作集中在列表两端(如添加或删除元素)。
5.8.2 ExtraSelection 简介
QTextEdit::ExtraSelection 用法
结构体组成
- 包含
QTextCursor和QTextCharFormat两个成员 QTextCursor定义文本位置或区间QTextCharFormat定义文本格式(颜色、字体等)
应用步骤
创建 ExtraSelection 对象并配置格式后,通过 setExtraSelections() 应用到编辑器:
cpp
QTextEdit::ExtraSelection selection;
selection.cursor = textEdit->textCursor();
selection.format.setBackground(Qt::yellow);
textEdit->setExtraSelections({selection});
高亮当前行实现
在 cursorPositionChanged 信号槽中动态设置高亮:
cpp
void Widget::oncursorPositionChanged() {
//设置高亮
QList<QTextEdit::ExtraSelection> extraselection;
QTextEdit::ExtraSelection ext;
ext.cursor = cursor;
QBrush qBrush(Qt::yellow);
ext.format.setBackground(qBrush);
ext.format.setProperty(QTextFormat::FullWidthSelection, true);
extraselection.append(ext);
ui->textEdit->setExtraSelections(extraselection);
}
截至目前,该项目已完成如下功能
