QT小案例实践
这是我学习 C++ 后,尝试使用 Qt 开发桌面应用的练习项目。在入门阶段参考了 B 站「社长_嵌入式」的 Qt 教程视频,收获很多。本文是我在编码过程中对知识点、功能实现与问题解决的总结,目的是为了 记录学习过程,方便以后回顾。项目代码是我边学边写的,可能包含一些 BUG 或不够完善的地方,如果您在调试时发现问题,可以尝试自行修改,也欢迎提出建议,共同进步!
这是我学习 C++ 后,尝试使用 Qt 开发桌面应用的练习项目。在入门阶段参考了 B 站「社长_嵌入式」的 Qt 教程视频,收获很多。
本文是我在编码过程中对知识点、功能实现与问题解决的总结,目的是为了 记录学习过程,方便以后回顾。
项目代码是我边学边写的,可能包含一些 BUG 或不够完善的地方,如果您在调试时发现问题,可以尝试自行修改,也欢迎提出建议,共同进步!
github链接:https://github.com/houshiyuan3-eng/MyQtProject
天气预报小案例总结

1 控制label组件的边框:
border-radius
2 QT在网络上获取Json数据的步骤:
-
QNetworkAccessManager *manger = new QNetworkAccessManager (this)//网络接口管理者
-
QNetWorkRequest req(QUrl(Qstring(网址)))
-
connect(manger,&QNetworkAccessManager::finished,this,&Widget::readHttpReply);//监听函数
-
判断是否接受成功 (QNetworkReply *reply)
int code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if(reply->error() == QNetworkReply::NoError&&code==200)
表示success;QByteArray data = reply->readAll();//接收数据
-
接受数据后转换为需要的数据:
QJsonDocument jsonObj = QJsonDocument::fromJson(dataJson);//获取数据
返回的内容有多重类型,根据类型判断接受的格式,要注意如何遍历:
例如:QJsonArray QJsonObject
循环遍历时候数据的类型用QJsonValue 表示
3 添加简单的弹窗事件简易版:
QMenu *menuQuit =new QMenu(this);
QAction *action =new QAction(QIcon(":/tuichu.png"),tr("退出"),this);
menuQuit->addAction(action);
connect(menuQuit,&QMenu::triggered,this,[=]{
this->close();
});
4 窗口不显示上边的调节部分:
setWindowFlag(Qt::FramelessWindowHint)
5 固定窗口的大小:
setFixedSize(a,b);
6 自定义鼠标点击事件:
void mousePressEvent(QMouseEvent *event);
void Widget::mousePressEvent(QMouseEvent *event)
{
if(event->button()==Qt::LeftButton){
qDebug()<<"left button";
offend = event->globalPos()-this->pos();
//event->globalPos()相当于整个桌面坐标,this->pos()相对于窗口的坐标
}
if(event->button()==Qt::RightButton){
menuQuit->exec(QCursor::pos());
}
}
7 鼠标移动事件:使鼠标可以拖动窗口
void mouseMoveEvent(QMouseEvent *event) override;
void Widget::mouseMoveEvent(QMouseEvent *event)
{
this->move(event->globalPos()-offend);
}
8 显示某个组件的坐标
ui->label.x();//显示X的坐标
ui->label.width();//组件宽度
9 事件过滤器
bool eventFilter(QObject *watcher,QEvent *event);//都文件中重写时间过滤器函数
ui->widget_hightemp->installEventFilter(this);
ui->widget_lowtemp->installEventFilter(this);//给对应组件添加监听事件
bool Widget::eventFilter(QObject *watcher, QEvent *event)
{
if (watcher == ui->widget_hightemp && event->type() == QEvent::Paint) {
drawHighTempLine();
return true;
}
if (watcher == ui->widget_lowtemp && event->type() == QEvent::Paint) {
drawLowTempLine();
return true;
}
return QWidget::eventFilter(watcher, event); // 其他情况交回父类处理
}
车辆仪表盘案例总结

1paintEvent 触发时机
| 触发情况 | 是否自动触发 | 说明 |
|---|---|---|
| 窗口首次显示(show() 后) | ✅ 自动 | 首次绘制界面 |
| 窗口从被遮挡变为可见(如最小化恢复) | ✅ 自动 | 重新绘制暴露的部分 |
调用 update() |
✅ 异步自动 | 请求重绘,推荐使用 |
调用 repaint() |
✅ 同步立即 | 立即重绘,少用为妙 |
| 窗口大小改变(resize) | ⚠️ 可能自动 | 通常伴随 resizeEvent,可能触发 paintEvent |
| 手动指定区域更新(如 update(QRect)) | ✅ 异步自动 | 只更新指定区域 |
| 系统或 Qt 认为需要重绘某个区域 | ✅ 自动 | 比如部分失效等 |
2 在某位置插入图片
QPainter painter(this);
painter.drawPixmap(rect,QPixmap(":/icon/CarLogo.png"));
3 渐变色设置步骤
QRadialGradient RGradient(0,0,radical-30);//调用不同渐变色方法,设置不同的形状
RGradient.setColorAt(1,QColor(255,0,0,200));//设置颜色变化比例
// RGradient.setColorAt(0.98,QColor(255,0,0,120));
RGradient.setColorAt(0.9,QColor(255,0,0,100));
RGradient.setColorAt(0.8,QColor(0,0,0,100));
RGradient.setColorAt(0.0,QColor(0,0,0,0));
painter.setBrush(RGradient);
painter.setPen(Qt::NoPen);
painter.drawPie(QRect(-radical+12,-radical+12,radical*2-30,radical*2-30),-150*16,-60*(240*1.0/60)*16);//在指定部分画
4 绘制自定义形状
painter.setBrush(QBrush(Qt::white));
static const QPointF points[4] = {
QPointF(0,1),
QPointF(150.0,0),
QPointF(150.0,1),
QPointF(0,10)
};
// painter.drawLine(50,0,radical-50,0);
painter.drawPolygon(points,4);
5 字体设置
QFont font("华文宋体",30);
font.setBold(true);
painter.setFont(font);
Qt网络通信助手总结

1 实现的功能
该程序实现了一个 基于 TCP 协议的简易聊天/通信系统,支持:
服务端功能:
- 监听指定的 IP 和端口
- 接收多个客户端的连接
- 显示客户端的连接、断开信息
- 接收来自客户端的数据并显示
- 向单个客户端或所有客户端发送消息
- 管理客户端连接(如断开、端口选择等)
客户端功能:
- 连接到指定的服务器 IP 和端口
- 发送消息到服务器
- 接收并显示来自服务器的消息
- 处理连接状态(成功、失败、超时等)
- 断开连接
2 使用的 Qt 模块与核心类
| Qt 模块 | 核心类 / 功能 | 用途说明 |
|---|---|---|
| Core | QObject, QWidget, qDebug, QString, etc. | 基础对象、字符串处理、调试输出等 |
| Gui | QWidget, QTextEdit, QLineEdit, QPushButton, etc. | 用户界面组件 |
| Network | QTcpServer, QTcpSocket, QHostAddress, QAbstractSocket, QNetworkInterface | TCP 通信相关类 |
| Widgets | QWidget, QVBoxLayout, QMessageBox, etc. | 图形界面控件与布局 |
3 网络通信相关类与功能
3.1QTcpServer —— TCP 服务端
主要功能:监听指定的 IP 和端口,接受客户端连接,管理多个客户端连接
关键函数与信号:
server->listen(QHostAddress, quint16 port):开始监听server->hasPendingConnections():是否有等待接受的连接server->nextPendingConnection():接受一个新连接,返回 QTcpSocket*- 信号:
newConnection():当有新客户端连接时触发
代码示例:
server = new QTcpServer(this);
connect(server, SIGNAL(newConnection()), this, SLOT(on_newClient_Connnect()));
...
if(!server->listen(QHostAddress(ip), port)) { ... }
3.2 QTcpSocket —— TCP 客户端通信套接字
主要功能:用于与服务端建立的连接,进行数据的发送
可以使服务端与单个客户端连接的套接字,也可以是客户端用来连接服务器的套接字
关键函数:
connectToHost(ip, port):连接到指定的服务器write(data):发送数据(字节数组)readAll():读取所有接收到的数据close():关闭连接
重要信号:
readyRead():当有数据可读时触发connected():连接成功时触发disconnected()/stateChanged():连接状态变化errorOccurred(QAbstractSocket::SocketError):发生错误时触发
代码示例:
client = new QTcpSocket(this);
connect(client, SIGNAL(readyRead()), this, SLOT(mRead_Data_From_Server()));
connect(client, SIGNAL(connected()), this, SLOT(onConnect()));
connect(client, SIGNAL(errorOccurred(...)), this, SLOT(onError(...)));
3.3 QHostAddress & QAbstractSocket
QHostAddress:表示 IP 地址,支持 IPv4 / IPv6QAbstractSocket:QTcpSocket 的父类,提供通用的套接字状态和操作
获取本机地址:
//遍历本机所有网络接口地址,筛选出 IPv4 地址供用户选择
QList<QHostAddress> address = QNetworkInterface::allAddresses();
for(QHostAddress tmp : address){
if(tmp.protocol() == QAbstractSocket::IPv4Protocol){
ui->comboBox_serverIPAddress->addItem(tmp.toString());
}
}
4 信号与槽机制(Qt 的核心机制!)
Qt 使用 信号与槽(Signals & Slots) 机制进行对象间的通信,替代传统回调,更加安全和灵活。
信号与槽的基本用法:
connect(sender, SIGNAL(signalName(params...)), receiver, SLOT(slotName(params...)));
或者(推荐使用新式语法,更类型安全):
connect(sender, &SenderClass::signalName, receiver, &ReceiverClass::slotName);
本案例中的信号与槽连接举例:
| 信号来源 | 信号 | 槽函数 | 作用 |
|---|---|---|---|
| QTcpServer | newConnection() | on_newClient_Connnect() | 有新客户端连入 |
| QTcpSocket | readyRead() | on_readyRead_handler() / mRead_Data_From_Server() | 收到数据 |
| QTcpSocket | stateChanged() | mstateChanged() | 套接字状态改变 |
| QTcpSocket | errorOccurred() | onError() | 出现网络错误 |
| QTimer | timeout() | onTimeOut() | 连接超时处理 |
| 自定义(或 ComboBox) | on_Combox_click | Combox_refush() | 刷新端口列表(自定义信号) |
5 UI 界面与控件交互
5.1 常见控件
QTextEdit:用于显示聊天内容 / 日志QLineEdit:输入 IP、端口、消息内容QPushButton:触发连接、发送、停止等操作QComboBox:选择 IP、端口、发送对象等
5.2 布局管理
- 使用了
QVBoxLayout(垂直布局),通过代码设置:
this->setLayout(ui->verticalLayout);
- 一般更推荐在 Qt Designer 中直接拖放布局,而不是代码动态设置,除非有特殊需求
5.3 将组件上升至函数
//头文件:
class myCombox : public QComboBox
{
Q_OBJECT
public:
myCombox(QWidget *parent);
protected:
void mousePressEvent(QMouseEvent *e) override;
signals:
void on_Combox_click();
};
//源文件:
#include "mycombox.h"
#include <QMouseEvent>
myCombox::myCombox(QWidget *parent):QComboBox(parent){
}
void myCombox::mousePressEvent(QMouseEvent *e)
{
if(e->button()==Qt::LeftButton){
emit on_Combox_click();
}
QComboBox::mousePressEvent(e);
}
//主函数:
connect(ui->comboBox_ChoosePort,&myCombox::on_Combox_click,this,&Widget::Combox_refush);
//调用函数:
void Widget::Combox_refush()
{
ui->comboBox_ChoosePort->clear();
qDebug()<<"combox refush";
QList<QTcpSocket *> tcpclients = server->findChildren<QTcpSocket *>();
//试图查找当前 server 对象下所有的 QTcpSocket 子对象
if(tcpclients.size()!=0){
for(QTcpSocket *tmp :tcpclients){
ui->comboBox_ChoosePort->addItem(QString::number(tmp->peerPort()));
}
ui->comboBox_ChoosePort->addItem("ALL");
}
}
6 其他零散知识
6.1 字节流处理(数据的发送与接收)
- 使用
QByteArray作为数据载体 write()发送数据readAll()读取数据- 注意编码问题,尤其是中文。推荐使用
toUtf8()而非toStdString().c_str()
6.2 光标显示
通过 QTextCursor控制文本滚动与光标位置,提升用户体验:
ui->textEdit_serverContent->moveCursor(QTextCursor::End);
ui->textEdit_serverContent->ensureCursorVisible();
6.3 消息框提示(QMessageBox)
//用于提示错误,警告等
QMessageBox msgbox;
msgbox.setWindowTitle("监听失败");
msgbox.setText("端口号被占用!");
msgbox.exec();
6.4定时器(QTimer)——用于连接超时
客户端连接时,启动一个 单次定时器 检测是否连接成功,防止一直卡死:
timer = new QTimer(this);
timer->setSingleShot(true);
timer->setInterval(2000);
connect(timer, SIGNAL(timeout()), this, SLOT(onTimeOut()));
timer->start();
7 总结
| 知识点分类 | 具体内容 |
|---|---|
| Qt 基础 | QWidget、信号槽、构造/析构、UI 加载(setupUi)、布局管理 |
| 网络编程 | QTcpServer、QTcpSocket、TCP 通信流程、IP 地址处理、端口监听 |
| 信号与槽 | 事件驱动编程、新旧信号槽语法、自定义信号处理 |
| 套接字通信 | readyRead、connected、disconnected、errorOccurred、stateChanged |
| UI 交互 | 按钮、输入框、下拉框、文本框、按钮状态控制 |
| 数据收发 | QByteArray、write()、readAll()、字符串编码(toUtf8) |
| 日志与提示 | QTextEdit、QTextCursor、QMessageBox |
| 定时器 | QTimer、超时处理、单次定时 |
| 网络工具类 | QHostAddress、QNetworkInterface、QAbstractSocket |
| 多客户端管理 | nextPendingConnection、findChildren、动态管理套接字列表 |
| 代码结构与设计 | 功能分离、状态管理、模块化思想(可优化点) |
基于 Qt 的串口调试助手

1 核心功能模块
| 模块 | 功能描述 |
|---|---|
| 1. 串口通信 | 打开/关闭串口,设置波特率、数据位、校验位、停止位、流控,实现串口数据的收发 |
| 2. 数据发送 | 支持手动发送、自动定时发送、循环批量发送;支持 HEX / 文本格式发送 |
| 3. 数据接收 | 实时接收串口数据并显示,支持 HEX 显示切换,统计收发字节数 |
| 4. 数据记录与保存 | 保存接收/发送历史到文件,支持导出文本内容 |
| 5. 快捷按钮控制 | 通过多个按钮(pushButton_1 ~ pushButton_9)快速填充发送框内容并发送 |
| 6. 界面交互优化 | 包括面板隐藏/展开、时间显示、状态提示、自动滚动、输入框与复选框联动等 |
| 7. 参数配置持久化 | 支持从文件加载/保存输入框和复选框的状态(如一键配置导入导出) |
| 8. 动态控件管理 | 通过 findChild 动态查找和绑定多个按钮、输入框、复选框,实现可扩展 UI |
2 串口通信相关(QSerialPort 核心知识点)
2.1 QSerialPort 类
用于控制电脑上的串口硬件,进行数据的收发
需要设置的参数包括:
- 端口名称(COM1, /dev/ttyUSB0…)
- 波特率(BaudRate)
- 数据位(DataBits)
- 校验位(Parity)
- 停止位(StopBits)
- 流控(FlowControl)
2.2 关键函数
| 函数 | 作用 |
|---|---|
setPortName() |
设置串口号 |
setBaudRate() |
设置波特率,如 9600、115200 |
setDataBits() |
数据位,如 8 |
setParity() |
校验位,如 NoParity、EvenParity |
setStopBits() |
停止位,如 OneStop |
setFlowControl() |
流控,如 NoFlowControl |
open(QIODevice::ReadWrite) |
打开串口 |
close() |
关闭串口 |
write() |
发送数据 |
readAll() |
读取所有可用数据 |
isOpen() |
判断是否已打开 |
2.3信号
| 信号 | 说明 |
|---|---|
readyRead() |
当串口有数据到达时触发,用于接收数据 |
3 UI 界面与控件交互设计
3.1 控件类型
- 按钮类:QPushButton(发送、清空、保存、打开串口、快捷按钮等)
- 输入框类:QLineEdit(发送内容、定时发送间隔等)
- 复选框类:QCheckBox(HEX 发送、自动换行、定时发送开关等)
- 文本显示区:QTextEdit(历史记录、发送记录)
- 下拉框类:QComboBox(串口列表、波特率、校验位等)
- 分组框:QGroupBox(用于组织界面模块,如历史面板、文本面板)
- 标签类:QLabel(时间显示、状态提示等)
3.2 动态控件查找与绑定
使用了 findChild<T>()动态查找控件,并为多个类似的按钮/输入框/复选框进行了 “批量绑定”
for(int i=1;i<=9;i++){
QString btnname = QString("pushButton_%1").arg(i);
QPushButton *btn = findChild<QPushButton *>(btnname);
...
connect(btn, SIGNAL(clicked()), this, SLOT(on_command_btn_clicked()));
}
4 文件操作
- 保存通信记录 到 txt 文件:
on_pushButton_SaveRecord_clicked() - 保存输入框/复选框配置:
on_pushButtonSave_clicked() - 加载配置:
on_pushButtonLoad_clicked()
使用到的类:
QFileDialog:弹出文件选择对话框QFile:操作文件(打开、读写、关闭)QTextStream:以文本形式读写文件内容
5 时间显示相关功能
windowtimer = new QTimer(this);
connect(windowtimer, &QTimer::timeout, [=]{
// 时间显示
QDateTime currenttime = QDateTime::currentDateTime();
QDate date = currenttime.date();
int year = date.year();
int month = date.month();
int day = date.day();
QTime time = currenttime.time();
int hour = time.hour();
int minute = time.minute();
int second = time.second();
mytime = QString("%1-%2-%3 %4:%5:%6")
.arg(year, 2, 10, QChar('0'))
.arg(month, 2, 10, QChar('0'))
.arg(day, 2, 10, QChar('0'))
.arg(hour, 2, 10, QChar('0'))
.arg(minute, 2, 10, QChar('0'))
.arg(second, 2, 10, QChar('0'));
ui->label_times->setText(mytime);
});
windowtimer->start(1000); // 每隔 1000 毫秒(即 1 秒)触发一次 timeout()
5.1 QDateTime / QDate / QTime —— Qt 提供的时间日期类
Qt 提供了一整套非常方便的时间日期处理类
| 类 | 作用 |
|---|---|
QDateTime |
包含日期和时间,可通过 currentDateTime()获取当前系统时间 |
QDate |
只包含日期部分(年、月、日) |
QTime |
只包含时间部分(时、分、秒) |
QDateTime currenttime = QDateTime::currentDateTime(); // 获取当前日期时间
QDate date = currenttime.date(); // 提取日期部分
QTime time = currenttime.time(); // 提取时间部分
- 年:
date.year() - 月:
date.month() - 日:
date.day() - 时:
time.hour() - 分:
time.minute() - 秒:
time.second()
5.2 QString::arg() —— 格式化字符串(重点!)
使用了 QString::arg()方法,对数字进行 格式化拼接,确保每一位数字都是 两位数,不足的前面补零
mytime = QString("%1-%2-%3 %4:%5:%6")
.arg(year, 2, 10, QChar('0')) // 年,占2位,不足补0
.arg(month, 2, 10, QChar('0')) // 月
.arg(day, 2, 10, QChar('0')) // 日
.arg(hour, 2, 10, QChar('0')) // 时
.arg(minute, 2, 10, QChar('0')) // 分
.arg(second, 2, 10, QChar('0')); // 秒
参数解释:
QString::arg(value, 最小宽度, 进制, 填充字符)
基于 Qt 的轻量级记事本(Notepad)项目的核心代码

功能包括:
- 打开 / 保存 / 关闭文本文件
- 使用快捷键(Ctrl+O、Ctrl+S、Ctrl+Shift+/-)进行快捷操作
- 自定义文本编辑区(继承自 QTextEdit,支持 Ctrl+滚轮缩放字体)
- 显示当前光标所在 行号和列号
- 关闭窗口时的 确认对话框
- 文档修改提示与保存提醒
- 使用 Qt 的信号槽、事件处理、快捷键机制等核心功能
1 功能简介
| 功能模块 | 功能描述 |
|---|---|
| 1. 文件操作 | 打开文本文件(支持 .txt)、保存文件、关闭文件并提示保存 |
| 2. 编辑区增强 | 自定义 QTextEdit,支持通过 Ctrl + 鼠标滚轮缩放字体大小 |
| 3. 快捷键支持 | 支持常用的快捷键操作,如:• Ctrl+O:打开文件• Ctrl+S:保存文件• Ctrl+Shift+=:增大字体• Ctrl+Shift±:减小字体 |
| 4. 光标位置提示 | 实时显示当前光标所在的 行号和列号(如:行: 3, 列: 15) |
| 5. 用户交互与安全 | 关闭窗口时弹出确认对话框,保存前提示,防止误操作丢失内容 |
| 6. 界面与布局管理 | 使用 Qt Designer 布局,并动态设置窗口标题、布局响应等 |
2 信号与槽机制(核心交互逻辑)
2.1 快捷键触发操作
QShortcut *shortcutopen = new QShortcut(QKeySequence(tr("Ctrl+O")), this);
connect(shortcutopen, &QShortcut::activated, [=]{
on_btn_open_clicked();
});
- 使用
QShortcut绑定快捷键(如 Ctrl+O、Ctrl+S) - 当用户按下快捷键时,触发对应的槽函数(比如打开文件、保存文件)
2.2 文本编辑区增强功能(MyTextEdit 类)
创建了一个自定义控件类:
class MyTextEdit : public QTextEdit
它继承自 QTextEdit,并 重写了 3 个事件处理函数,用于增强编辑区的功能:
① wheelEvent() —— Ctrl + 滚轮缩放字体
void MyTextEdit::wheelEvent(QWheelEvent *e)
{
if(onkeypressed){ // 只有按下 Ctrl 时才响应滚轮
if(e->angleDelta().y() > 0) zoomIn(); // 放大字体
else zoomOut(); // 缩小字体
e->accept();
} else {
QTextEdit::wheelEvent(e); // 默认行为
}
}
功能:
- 当用户按住 Ctrl 键 + 滚轮向上/向下,字体就会放大或缩小
- 利用了
zoomIn()和zoomOut()这两个 QTextEdit 内置的便捷函数
限制:
- 只有检测到
Key_Control被按下时(通过 keyPressEvent / keyReleaseEvent 管理),滚轮事件才会触发缩放
② keyPressEvent() / keyReleaseEvent() —— 检测 Ctrl 键状态
void MyTextEdit::keyPressEvent(QKeyEvent *e)
{
if(e->key() == Qt::Key_Control)
onkeypressed = 1; // Ctrl 按下
QTextEdit::keyPressEvent(e);
}
void MyTextEdit::keyReleaseEvent(QKeyEvent *e)
{
if(e->key() == Qt::Key_Control)
onkeypressed = 0; // Ctrl 释放
QTextEdit::keyReleaseEvent(e);
}
- 通过记录一个布尔变量
onkeypressed,标识当前是否按下了 Ctrl 键 - 这个状态被用于控制 滚轮是否触发缩放
3 文件操作
3.1 打开并读取文件内容
void Widget::on_btn_open_clicked()
{
QString filename= QFileDialog::getOpenFileName(this,tr("Open File"),"D:/QTtest/QT_notebook/notebook",tr("Text(*.txt)"));
ui->textEdit->clear();
file.setFileName(filename);
this->setWindowTitle(filename+"-侯世源的记事本");
if(!file.open(QIODevice::ReadWrite| QIODevice::Text)){
qDebug()<<"open file error";
}
QTextStream in(&file);
while(!in.atEnd()){
QString context =in.readLine();
ui->textEdit->append(context);
}
// file.close();
}
3.2 保存文件
void Widget::on_btn_save_clicked()
{
if(!file.isOpen()){
QString filename = QFileDialog::getSaveFileName(this,tr("Open File"),"D:/QTtest/QT_notebook/notebook/untitled.txt",tr("Text(*.txt)"));
file.setFileName(filename);
if(!file.open(QIODevice::WriteOnly)|QIODevice::Text){
qDebug()<<"file open error";
}
}
QTextStream out(&file);
QString context= ui->textEdit->toPlainText();
QMessageBox messagebox;
messagebox.setInformativeText("文件保存成功!");
messagebox.setStandardButtons(QMessageBox::Ok);
int ret = messagebox.exec();
// file.close();
}
3.3 关闭文件逻辑
(1) 关闭按钮逻辑(on_btn_close_clicked)
- 弹出一个 QMessageBox 询问是否保存、丢弃或取消
- 支持三种选项,交互非常专业,是记事本类软件的标配
(2)关闭文件事件
void Widget::on_btn_close_clicked()
{
// qDebug()<<"click";
QMessageBox msgBox;
msgBox.setText("The document has been modified.");
msgBox.setInformativeText("Do you want to save your changes?");
msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
msgBox.setDefaultButton(QMessageBox::Save);
int ret = msgBox.exec();
switch (ret) {
case QMessageBox::Save:
on_btn_save_clicked();
break;
case QMessageBox::Discard:
ui->textEdit->clear();
if(file.isOpen()){
file.close();
ui->textEdit->clear();
this->setWindowTitle("侯世源的记事本");
}
break;
case QMessageBox::Cancel:
// Cancel was clicked
break;
default:
// should never be reached
break;
}
}
(3) 窗口关闭事件(closeEvent)
void Widget::closeEvent(QCloseEvent *event)
{
int ret = QMessageBox::warning(this,tr("侯世源的记事本"),tr("Do you want close the window?\n close the window"),QMessageBox::Ok|QMessageBox::No);
switch (ret) {
case QMessageBox::Ok:
event->accept();
break;
case QMessageBox::No:
event->ignore();
default:
break;
}
}
4 光标位置实时显示(行号 / 列号),高亮显示
4.1 显示行号
实现函数:oncursorPositionChanged()
QTextCursor tcur = ui->textEdit->textCursor();
int blockNumber = tcur.blockNumber(); // 当前行号(从0开始)
int columnNumber = tcur.columnNumber(); // 当前列号(从0开始)
ui->labelposition->setText("行: " + QString::number(blockNumber) + " , 列: " + QString::number(columnNumber));
- 该函数与
textEdit的cursorPositionChanged()信号连接 - 每当光标移动时,实时更新一个标签控件(比如叫
labelposition),显示当前光标位于 第几行、第几列
4.2高亮显示选中行
QList<QTextEdit::ExtraSelection> extraSelection;
QTextEdit::ExtraSelection ext;
ext.cursor = ui->textEdit->textCursor();
QBrush qbrush(Qt::lightGray);
ext.format.setBackground(qbrush);
ext.format.setProperty(QTextFormat::FullWidthSelection, true);
extraSelection.append(ext);
ui->textEdit->setExtraSelections(extraSelection);
①QTextEdit::ExtraSelection 是什么:
Qt 定义的一个 结构体(或类),用来描述一个“额外的选中区域样式”,包括:
- 哪一部分文本/区域要高亮(通过 cursor 指定)
- 这个区域的文本格式(比如背景色、字体颜色等)
- 是否整行高亮等属性
声明(简化)大致如下:
struct ExtraSelection {
QTextCursor cursor; // 高亮区域对应的文本光标位置
QTextCharFormat format; // 该区域的文本格式(比如背景色)
};
②代码逐行解析:
(1) 创建一个 ExtraSelection 列表
QList<QTextEdit::ExtraSelection> extraSelection;
- 这是一个列表,可以存放 多个高亮区域(比如同时高亮多行)
- 但在这里只高亮 当前光标所在的一行,所以只添加了一个
(2) 创建一个 ExtraSelection 对象
QTextEdit::ExtraSelection ext;
(3) 设置要高亮的区域 —— 当前光标所在行
ext.cursor = ui->textEdit->textCursor();
textCursor()返回当前 QTextEdit 中光标的位置- 它代表 当前光标所在的行、列
- 默认情况下,ExtraSelection 会高亮光标所在位置的“字符区域”
- 但配合下面的属性,我们可以让它高亮 整行
(4) 设置高亮的背景颜色
QBrush qbrush(Qt::lightGray);
ext.format.setBackground(qbrush);
QBrush是 Qt 的画刷,用于定义填充颜色Qt::lightGray是浅灰色 —— 你也可以换成别的颜色,比如:Qt::yellow``QColor(200, 200, 255)自定义 RGB / RGBA 值ext.format.setBackground(qbrush)表示:将这个区域的背景色设置为浅灰色,实现高亮效果
(5) 设置为“整行高亮”
ext.format.setProperty(QTextFormat::FullWidthSelection, true);
关键!这是实现“整行高亮”的核心属性。
QTextFormat::FullWidthSelection是一个枚举值,表示:让选中的区域自动拉伸至整行宽度,即使光标没有选中到行尾- 如果不设置这个属性:高亮区域可能只覆盖光标附近的几个字符
- 设置后:高亮会自动填充 从行首到行尾的整个水平范围,视觉上就是“整行高亮”
(6) 把这个高亮区域加入列表
extraSelection.append(ext);
- 我们把配置好的高亮对象
ext,放入列表extraSelection中
(7) 应用高亮到文本编辑器
ui->textEdit->setExtraSelections(extraSelection);
- 这是真正“生效”的一步!
- 调用
setExtraSelections()后,Qt 会在下一帧渲染时,把列表中的高亮区域绘制出来 - 它 不会影响用户真实选中的文本,只是视觉上的额外提示
更多推荐


所有评论(0)