C++ Qt5 范例开发大全

作者:Longki|186 页|以 Windows + Qt 5.1.1 (MinGW) 为环境,14 章共 80+ 个可运行范例,覆盖 Qt 桌面开发常用模块。

一、书籍定位与特点

  • 面向 Qt 初学者的”菜谱式”教程:每个范例按”需求 → 参照工程 → .h 声明 → .cpp 实现”组织,代码可直接拷贝运行。
  • 技术栈:Qt 5.1.1 + MinGW 4.8 + Qt Creator,全部基于 C++ Widgets(非 QML/Qt Quick)。
  • 知识覆盖:窗体、控件、文件、图形、多媒体、系统 API、注册表、数据库、网络(TCP/UDP/SMTP)、进程线程、加密、打包部署,形成完整的 Windows 桌面应用开发链路。
  • 局限:部分方案已过时(QAxWidget 播 Flash、Windows 注册表、wininet.dll),但核心 Widgets/Network/Sql/Concurrent API 在 Qt5/Qt6 中仍适用。

二、Qt 框架核心概念

2.1 三大窗口基类

基类用途典型场景
QMainWindow带菜单栏、工具栏、状态栏的主窗口应用主框架,中央放编辑区/画布
QWidget所有 UI 对象的基类自定义窗口、登录框等简单界面
QDialog对话框基类,模态/非模态短期任务、文件选择、参数配置

2.2 信号与槽(Signals/Slots)

Qt 用类型安全的 signal/slot 替代回调函数,是组件通信的核心机制:

connect(button, SIGNAL(clicked()), this, SLOT(onClick()));
// Qt5 新语法(编译期检查):
connect(button, &QPushButton::clicked, this, &MainWindow::onClick);

2.3 元对象系统(moc)

  • Qt 的 Q_OBJECT 宏触发 moc(Meta Object Compiler)生成信号槽元代码。
  • 自定义类用信号槽必须继承 QObject 并在类声明中加 Q_OBJECT。
  • pro 文件中 QT += 控制模块:sql(数据库)、network(网络)、qaxcontainer(ActiveX)。

三、窗体与界面(第 2、4 章)

3.1 窗体控制常用 API

setWindowTitle("标题");
setMaximumSize(300,300); setMinimumSize(300,300);  // 固定大小
move(100,100);                                      // 位置
setStyleSheet("background:red");                    // QSS 样式
setWindowIcon(QIcon(":/ico"));                      // 图标(资源文件)
setWindowFlags(Qt::FramelessWindowHint);            // 无边框
setWindowFlags(Qt::WindowCloseButtonHint);          // 只留关闭按钮
setAttribute(Qt::WA_TranslucentBackground, true);   // 背景透明

3.2 无边框窗体拖动

重写三个鼠标事件,用全局坐标差移动窗口:

void mousePressEvent(QMouseEvent *e)   { last = e->globalPos(); }
void mouseMoveEvent(QMouseEvent *e)    { move(x()+e->globalX()-last.x(),
                                              y()+e->globalY()-last.y()); }
void mouseReleaseEvent(QMouseEvent *e) { /* 同 move 逻辑 */ }

3.3 标准对话框

  • QFileDialog::getOpenFileName() — 文件选择,可用过滤器 "Text(*.txt);;All(*.*)"
  • QColorDialog::getColor() — 颜色选择,配合 QPalette 改控件颜色
  • QMessageBox::warning/information() — 消息提示
  • QCalendarWidget — 日历,点击信号 clicked(QDate)

3.4 定时器刷新

QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &MainWindow::onTick);
timer->start(1000);                 // 周期 1 秒
QTimer::singleShot(3000, obj, SLOT(close()));  // 单次延时

四、常用控件全景(第 3 章)

4.1 输入控件

控件要点
QPushButtonclicked/released 信号;setEnabled(false) 禁用
QLabel支持 QSS:font-size/color/font-weight/font-style
QLineEditsetMaxLength()、setEchoMode(Password) 密码框
QTextEdit富文本/HTML(<br/> 换行),setText()
QPlainTextEdit纯文本多行,setPlainText()
QComboBoxaddItems(QStringList),currentText()
QFontComboBox字体选择下拉框,系统字体枚举
QSpinBoxsetRange(0,200)、setValue()、setPrefix/setSuffix
QTimeEdit/QDateEdit配合 QDateTime::currentDateTime() 初始化

4.2 选择控件

  • QRadioButton:互斥单选,setChecked(true) 默认项,用 sender() 判断信号来源。
  • QCheckBox:多选,checkState() == Qt::Checked 判断,取消选中时用 QString::replace() 移除文本。
  • QScrollBar:与 SpinBox 双向绑定 — 两者 valueChanged(int) 互连可实现联动。

4.3 Model/View 控件(重点)

Qt 的模型/视图架构是数据展示的核心:

// 列表:QStringListModel
QStringList data{"数学","语文"};
listView->setModel(new QStringListModel(data));
 
// 树:QStandardItemModel + appendRow 建层级
auto *model = new QStandardItemModel(3, 2);  // 3行2列
model->setHorizontalHeaderItem(0, new QStandardItem("列名"));
auto *parent = new QStandardItem("外语");
parent->appendRow(new QStandardItem("外语A"));  // 子节点
 
// 表格:setItem(row, col, item)
model->setItem(0, 0, new QStandardItem("数据"));
tableView->setEditTriggers(QAbstractItemView::NoEditTriggers); // 只读

4.4 布局管理

  • QHBoxLayout / QVBoxLayout:横/纵排列,addWidget()、setSpacing()。
  • QGridLayout:网格,addWidget(w, row, col, rowSpan, colSpan)。
  • QGroupBox:带标题的分组容器,内部嵌套其他布局。
  • QTabWidget:多标签页,addTab(new TabWidget, "名称"),每个 tab 是独立 QWidget 子类。

4.5 菜单、工具栏与托盘

// QAction = 命令对象,可同时挂在菜单和工具栏
auto *act = new QAction(QIcon(":/new"), tr("新建"), this);
act->setShortcut(QKeySequence("Ctrl+N"));
act->setStatusTip("状态栏提示");
connect(act, &QAction::triggered, this, &MainWindow::newFile);
 
menuBar()->addMenu(tr("文件"))->addAction(act);
addToolBar(tr("工具"))->addAction(act);
 
// 系统托盘
auto *tray = new QSystemTrayIcon(QIcon(":/ico"), this);
tray->setToolTip("提示");
tray->setContextMenu(trayMenu);
tray->show();
tray->showMessage("标题","内容", QSystemTrayIcon::Information, 10000);

最小化到托盘:重写 changeEvent,检测 WindowStateChange + isMinimized() 后调 hide()。

五、文件与配置(第 5 章)

5.1 文件/目录操作

QDir().mkdir(path);                 // 创建文件夹,exists() 先判重
QFile file(path);
file.open(QIODevice::ReadWrite | QIODevice::Text);
file.write(content.toUtf8());       // 中文必须 toUtf8()
QFile::remove(path);                // 删除
QFile::rename(old, new);            // 重命名(用 QFileInfo 取目录)

文件编辑典型模式:QFileDialog 取路径 → QTextStream 流式读写 → atEnd() 循环。

5.2 INI 配置文件(QSettings)

auto *ini = new QSettings("config.ini", QSettings::IniFormat);
ini->setValue("node/key", "value");          // 写:分组/键
QString v = ini->value("node/key").toString(); // 读

QSettings::NativeFormat 在 Windows 上即操作注册表(HKEY_CURRENT_USER\\Software\\...),同一套 API 兼顾 INI 和注册表。

5.3 XML 流式读写

  • 写:QXmlStreamWriter,writeStartDocument/Element、writeAttribute、writeTextElement,setAutoFormatting(true) 美化。
  • 读:QXmlStreamReader,readNext() 推进,isStartElement() + name() 判断节点,readElementText() 取值。

六、图形图像与特效(第 6 章)

6.1 两种绘图体系

  1. Graphics View 框架(场景/视图/图元):

    • QGraphicsScene 管理图元,addLine/addEllipse/addSimpleText。
    • QGraphicsView 视口显示场景,setCentralWidget(view)。
    • QPen 控制线条:setStyle(Qt::DashDotLine)、setWidth、setCapStyle。
  2. QPainter 低级绘制(重写 paintEvent):

    void paintEvent(QPaintEvent*) {
        QPainter p(this);
        p.drawPixmap(20,20,200,257, QPixmap(":/dog"));
        p.drawText(rect, Qt::AlignCenter, "文字");
    }

6.2 QImage 图像处理

QImage img; img.load(":/hd");
img.mirrored(true, false);        // 水平翻转
img.scaled(100,100, Qt::IgnoreAspectRatio);  // 缩放
QMatrix m; m.rotate(88);
img.transformed(m);               // 旋转
QPainter painter(&img); painter.shear(0.5,0); // 扭曲
image.save("out.jpg","JPG",100);  // quality 0-100

6.3 图形特效(QGraphicsEffect 体系)

auto *blur = new QGraphicsBlurEffect;       blur->setBlurRadius(5);
auto *colorize = new QGraphicsColorizeEffect; colorize->setColor(QColor(0,0,192));
auto *shadow = new QGraphicsDropShadowEffect; shadow->setOffset(8,8);
auto *opacity = new QGraphicsOpacityEffect;  opacity->setOpacity(0.5);
label->setGraphicsEffect(effect);  // 一个控件同时只能挂一个 effect

GIF 动画:QMovie + QLabel::setMovie() + movie->start()。

七、多媒体(第 7 章)

  • Qt 5.1 时代播放方案依赖 Windows ActiveX:QAxWidget 调用 WMP({22D6F312-...})或 Flash({d27cdb6e-...}),pro 加 CONFIG += qaxcontainer。
  • 现代 Qt 应改用 QMediaPlayer + QVideoWidget(Qt Multimedia),书中的播放状态机(Stopped/Paused/Playing)、进度条 blockSignals 防递归、timerEvent 轮询位置等思路仍可借鉴。
  • 逐帧图片动画:QTimer 周期切换 QPixmap::load 路径实现。

八、系统交互(第 8、9 章)

8.1 系统信息

QApplication::desktop()->screenGeometry();        // 屏幕分辨率
QHostInfo::localHostName();                       // 主机名
QHostInfo::fromName(name).addresses();            // 本机 IP(过滤 IPv4)
QHostInfo::lookupHost(url, this, SLOT(lookedUp(QHostInfo))); // 异步 DNS
QProcess::systemEnvironment();                    // 全部环境变量

8.2 执行外部命令

auto *proc = new QProcess(this);
connect(proc, &QProcess::readyRead, this, &MainWindow::readOut);
proc->start("ipconfig");          // 也支持 start(cmd, QStringList args)
// readAll() 在槽中累积输出;注意路径/中文参数用参数列表更安全

8.3 键盘事件

重写 keyPressEvent(QKeyEvent*),用 event->key() == Qt::Key_Q 判断。

8.4 注册表(Windows)

QSettings 以 NativeFormat 直接读写 HKEY_CURRENT_USER\Software\...,书中示范修改 IE 主页(Main/Start Page)——仅作技术说明,实际开发应避免此类操作。

九、数据库(第 10 章)

9.1 驱动与连接

QT += sql
qDebug() << QSqlDatabase::drivers();          // 列出可用驱动 QSQLITE/QODBC...
QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE");
db.setDatabaseName("db.db");
db.open();

Access 通过 ODBC 连接串:DRIVER={Microsoft Access Driver (*.mdb)};DBQ=path;UID=;PWD=。

9.2 增删查与模型展示

// 参数化插入(防注入)
QSqlQuery q;
q.prepare("insert into person(name) values(:n)");
q.bindValue(":n","张三");
q.exec();
 
// 表模型直接绑表格
QSqlTableModel *m = new QSqlTableModel;
m->setTable("person"); m->select();
tableView->setModel(m);

SQLite 建表范例:id INTEGER PRIMARY KEY AUTOINCREMENT, name VARCHAR(50), time TIMESTAMP default CURRENT_TIMESTAMP。

十、网络编程(第 11 章,含金量最高)

10.1 TCP 聊天(C/S 架构)

服务端三层结构值得借鉴:

  • TcpServer : QTcpServer:重写 incomingConnection(socketDescriptor),每个连接创建一个 TcpSocket 存入 QList,广播时遍历 write。
  • TcpSocket : QTcpSocket:构造时连 readyRead → dataReceived,读到数据后 emit 信号交给 server 广播;断线 emit disconnected(descriptor) 供 server 清理列表。
  • 客户端 QTcpSocket::connectToHost(ip, port),维护在线状态布尔值,退出时发 “Leave Chat Room” 再 disconnectFromHost()。

10.2 UDP 局域网广播 + 文件传输

综合范例,架构清晰:

  • UDP 端口 45454,bind(ShareAddress | ReuseAddressHint),消息用 QDataStream 序列化,枚举 MessageType{Message, NewParticipant, ParticipantLeft, FileName, Refuse}。
  • 用户上线/下线通过广播消息同步,在线用户表 QTableWidget 维护(用户名/主机名/IP)。
  • 文件传输走独立 TCP(端口 6666):UDP 先协商文件名和双方 IP,接收方弹窗确认后启动 tcpclient,发送方 tcpserver 监听;带 TotalBytes/fileNameSize 包头、进度条、速度与剩余时间估算。
  • 细节:eventFilter 实现回车发送;QNetworkInterface::allAddresses() 获取本机 IPv4。

10.3 SMTP 发信

QTcpSocket 直连 smtp.qq.com:25,手工走 SMTP 协议:helo → auth login → base64(账号) → base64(密码) → mail from → rcpt to → data → . → quit。现代环境普遍用 465/587 + SSL/TLS(QSslSocket),且需授权码而非账号密码。

10.4 网络状态

QLibrary 动态加载 wininet.dll,解析 InternetGetConnectedState 函数指针判断拨号/局域网/代理。现代跨平台可用 QNetworkConfigurationManager。

十一、进程与线程(第 12 章)

11.1 进程管理器(Windows API)

CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0) 拍进程快照 → Process32First/Next 遍历 PROCESSENTRY32(szExeFile + th32ProcessID)→ 结束进程用 QProcess::start("Taskkill", {"/pid", pid})。

11.2 两种线程用法

  1. QThread:thread->start() 启动,静态函数 QThread::sleep(1) 挂起。书中直接在函数内 new QThread 但未重写 run(),仅演示 API;实际耗时任务应子类化 QThread 重写 run() 或用 worker-object moveToThread 模式。
  2. QRunnable + QThreadPool(轻量任务推荐):
    class Job : public QRunnable {
        void run() override { for(...) progressBar->setValue(i); }
    };
    QThreadPool::globalInstance()->start(new Job);  // 自动 delete
    注意:书中在 worker 线程直接更新 UI 控件是错误示范,Qt 要求 GUI 操作只能在主线程(应通过信号回传)。

十二、数据安全(第 13 章)

  • QByteArray:toBase64()/fromBase64()、toHex() —— 是编码不是加密。
  • MD5(Qt 内置):
    QCryptographicHash h(QCryptographicHash::Md5);
    h.addData("pwd");
    QString md5 = h.result().toHex();   // 单向,用于比对而非解密
  • AES:Qt 无内置,书中用第三方 TAesClass,演示 InitializePrivateKey(16,key) → OnAesEncrypt/Uncrypt 流程。生产环境建议用 QCryptographicHash 支持的 SHA 系列或外部 OpenSSL/libsodium。
  • 随机数:qsrand(QTime::currentTime().msec()+sec*1000) 播种,qrand()%1000;现代代码用 QRandomGenerator::global()->bounded(1000)。

十三、打包部署(第 14 章)

Windows 发布 Qt 程序的标准流程(书中工具古老,流程不变):

  1. Release 模式编译出 exe。
  2. 拷贝 exe 到空目录,用依赖检查工具(书中 hap-depends,现代用 windeployqt 或 Dependencies)找出缺失 DLL。
  3. 从 Qt 的 mingw48_32/bin 拷贝运行时 DLL;必须额外拷贝 plugins/platforms/qwindows.dll(保持 platforms 子目录结构),否则程序启动即崩。
  4. 打包:现代直接用官方 windeployqt --release xxx.exe 自动收集;安装包用 Inno Setup(脚本化、轻量)或 NSIS。

十四、可复用经验总结

  1. 资源文件管理:图标/图片统一放入 .qrc,用 :/前缀/别名 访问,避免部署时丢图。
  2. 中文编码:文件读写一律 toUtf8();源码中文字符串注意源码编码与 QString::fromUtf8。
  3. UI 与数据解耦:列表/树/表格一律走 Model/View,数据用 QStandardItemModel/QSqlTableModel,不要直接往控件里塞数据。
  4. 信号槽防循环:进度条双向联动时用 blockSignals(true) 包裹程序化设值。
  5. 网络通信协议设计:自定义协议先发定长包头(总长度、文件名长度),再发载荷;接收方按字节数状态机解析(书中 TCP 文件传输是好范例)。
  6. 线程铁律:worker 线程不能碰 QWidget;跨线程通信用信号槽(QueuedConnection 自动生效)。
  7. 跨平台意识:书中注册表/wininet/Taskkill/QAxWidget 均为 Windows-only;Linux/嵌入式(如树莓派)上需替换为跨平台 API。

关联笔记