Qt学习笔记01:Qt核心基础
Qt学习笔记01:Qt核心基础
一、Qt核心基础认知
Qt是一款跨平台的C++应用程序开发框架,由Qt Company(原Nokia)维护,凭借其简洁的API、强大的跨平台能力和丰富的功能模块,成为桌面(Windows/Linux/macOS)、嵌入式(ARM/Linux)、移动端(Android/iOS)等领域开发的主流选择。想要学好Qt,首先要掌握其核心基础认知,包括跨平台原理、版本与模块选择两部分核心内容。
1.1 跨平台原理
Qt的跨平台特性是其核心优势之一,核心实现逻辑分为封装系统API和自绘组件两部分,具体实现细节如下:
- 封装系统API:不同操作系统的底层核心接口(如窗口创建、文件操作、网络通信)存在本质差异:
- Windows系统:窗口创建依赖
CreateWindowExAPI,文件操作依赖CreateFile/ReadFile等API; - Linux系统:窗口创建依赖X11/Wayland协议的底层接口,文件操作依赖
open/read等POSIX标准API; - macOS系统:窗口创建依赖Cocoa框架的
NSWindow,文件操作依赖fopen/fread等BSD风格API。
Qt在这些原生API之上封装了一层统一的抽象接口(如QWidget封装窗口创建、QFile封装文件操作),开发者调用Qt的API时,Qt的底层适配层会根据当前运行的操作系统,自动将Qt API映射到对应的系统原生API,无需开发者针对不同系统编写差异化代码。
- Windows系统:窗口创建依赖
- 自绘组件:传统原生控件(如Windows的Button控件、Linux的GTK Button控件)的外观渲染、事件响应逻辑差异极大,Qt提供了基于
QWidget的自绘组件体系:- 组件的渲染逻辑(如按钮的绘制、文字的显示)由Qt的
QPainter模块统一实现,不依赖系统原生控件的渲染逻辑; - 组件的事件响应(如点击、拖拽)由Qt的事件循环系统统一处理,保证同一套代码在不同系统下的UI外观、交互行为100%一致。
- 组件的渲染逻辑(如按钮的绘制、文字的显示)由Qt的
1.2 版本与模块选择
1.2.1 版本选择
目前Qt的主流版本为Qt5(最新LTS版本5.15)和Qt6(最新LTS版本6.6),两者核心差异如下(补充技术细节):
- Qt5:
- 底层兼容C++11/14标准,编译器支持范围广(如MSVC 2013、GCC 4.8);
- 生态成熟,第三方库(如OpenCV、Boost)的Qt适配版本全覆盖;
- 模块耦合度略高(如Qt Gui模块包含部分Widgets功能);
- 是目前企业级项目(尤其是嵌入式、传统桌面应用)的主流选择,覆盖90%以上的开发场景。
- Qt6:
- 基于C++17重构,底层移除大量老旧代码,内存占用降低约15%,运行效率提升约20%;
- 模块化更精细(如将Qt Core拆分为Qt Core、Qt Core5Compat);
- 新增Qt Quick 3D(三维界面开发)、Qt WebAssembly(Web端适配)、Qt StateMachine(状态机框架)等新特性;
- 部分老旧第三方库(如Qt5的QAxContainer)兼容度不足,适合新项目、对性能/新特性有需求的场景。
1.2.2 模块选择
Qt的功能以“模块”为单位划分,分为核心模块(必选/高频使用)和扩展模块(按需引入),各模块的核心类与功能补充如下:
- 核心模块:
- Qt Core:Qt的核心基础模块,提供内存管理(父子对象机制)、容器类(QList/QMap)、事件处理(QEvent)、元对象系统(Q_OBJECT宏/反射)、基础数据类型(QString/QVariant)等底层能力,所有Qt项目默认依赖;核心类包括
QObject(所有Qt对象的基类)、QString(字符串)、QVariant(万能类型)、QTimer(定时器)。 - Qt Gui:提供图形渲染(QPainter)、字体(QFont)、图像(QImage/QPixmap)、颜色(QColor)、输入设备(QMouseEvent/QKeyEvent)等基础图形界面能力,是Qt Widgets/Qt Quick的依赖模块;核心类包括
QPainter(绘图)、QImage(图像处理)、QGuiApplication(图形界面应用入口)。 - Qt Widgets:提供传统桌面端UI组件(按钮、输入框、布局等),是桌面应用开发的核心模块;核心类包括
QWidget(所有控件的基类)、QPushButton(按钮)、QLineEdit(输入框)、QMainWindow(主窗口)。
- Qt Core:Qt的核心基础模块,提供内存管理(父子对象机制)、容器类(QList/QMap)、事件处理(QEvent)、元对象系统(Q_OBJECT宏/反射)、基础数据类型(QString/QVariant)等底层能力,所有Qt项目默认依赖;核心类包括
- 扩展模块:
- QtNetwork:网络通信(TCP/UDP/WebSocket),核心类
QTcpSocket/QTcpServer/QUdpSocket/QWebSocket; - Qt Sql:数据库操作,核心类
QSqlDatabase(数据库连接)/QSqlQuery(SQL执行); - Qt Concurrent:并行计算,核心接口
QtConcurrent::run(多线程任务); - Qt Multimedia:音视频处理,核心类
QMediaPlayer(音视频播放)/QCamera(相机)。
- QtNetwork:网络通信(TCP/UDP/WebSocket),核心类
二、Qt工程文件核心配置
Qt工程的核心配置文件是.pro文件(Qt Creator默认生成),采用基于Makefile的简化语法,掌握其配置规则是搭建Qt工程的基础,包括基础配置、子目录工程、条件编译三部分,以下补充更具体的配置规则和细节。
2.1 .pro文件基础配置
.pro文件的核心配置项包括QT模块、TARGET、SOURCES/HEADERS/FORMS,以下是优化后的基础Qt Widgets工程示例(补充配置项说明和扩展用法):
# 在项目文件中, 注释需要使用 井号(#)
# 1. QT模块配置:声明工程依赖的Qt模块,+=表示追加,-=表示移除,=表示覆盖
QT += core gui # 基础依赖:核心模块+图形模块
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets # Qt5+需显式添加widgets模块(Qt4中包含在gui中)
# 扩展用法:移除不需要的模块(如移除Qt Network)
# QT -= network
# 2. 编译特性配置:CONFIG用于设置编译模式、C++标准、工程特性等
CONFIG += c++17 # 指定使用C++17标准(Qt5.14+支持,Qt6默认C++17)
CONFIG += debug # 编译为调试版本(release为发布版本,debug_and_release为同时编译)
CONFIG += warn_on # 开启所有编译警告(warn_off关闭)
# 3. 宏定义配置:DEFINES用于定义预编译宏,等价于C++中的#define
DEFINES += QT_DEPRECATED_WARNINGS # 调用废弃函数时触发编译警告
DEFINES += APP_VERSION="\"1.0.0\"" # 定义字符串宏(需嵌套引号)
DEFINES += MAX_COUNT=100 # 定义数值宏
# 4. 工程输出配置
TARGET = QtBasicDemo # 工程编译后的可执行文件名称(Windows:.exe,Linux:无后缀,macOS:.app)
TEMPLATE = app # 工程类型:app=可执行程序,lib=静态/动态库,subdirs=子目录工程
DESTDIR = ./bin # 可执行文件输出目录(默认在构建目录)
OBJECTS_DIR = ./obj # 中间目标文件(.o/.obj)输出目录
MOC_DIR = ./moc # moc工具生成的代码输出目录(处理Q_OBJECT宏)
UIC_DIR = ./ui # uic工具生成的UI代码输出目录(处理.ui文件)
RCC_DIR = ./rcc # rcc工具生成的资源代码输出目录(处理.qrc文件)
# 5. 文件列表配置:SOURCES(源文件)/HEADERS(头文件)/FORMS(UI文件)/RESOURCES(资源文件)
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
# 6. 资源文件配置(可选):.qrc文件用于管理图片、字体等资源
# RESOURCES += res.qrc
2.2 子目录工程配置
当项目规模较大时(如拆分UI模块、网络模块、业务模块),需要使用子目录工程,核心是通过SUBDIRS配置子工程路径,补充子工程的依赖规则和进阶用法:
示例:主工程QtSubDirDemo.pro
# 声明工程类型为子目录工程(必须放在首位)
TEMPLATE = subdirs
# 子工程列表:按顺序编译(可通过.depends指定依赖)
SUBDIRS += ui_module \
network_module \
business_module
# 指定子工程依赖关系:先编译依赖的子工程,再编译当前子工程
network_module.depends = ui_module # network_module依赖ui_module
business_module.depends = ui_module network_module # business_module依赖前两个模块
# 为每个子工程指定.pro文件路径(若子工程目录名与.pro文件名一致,可省略.file配置)
ui_module.file = ui_module/ui_module.pro
network_module.file = network_module/network_module.pro
business_module.file = business_module/business_module.pro
# 扩展:设置子工程的构建目录(默认在主工程构建目录下)
ui_module.builddir = ./build/ui_module
network_module.builddir = ./build/network_module
子工程ui_module.pro示例(补充库类型配置):
QT += widgets
TEMPLATE = lib # 子工程可编译为库(静态库/动态库)
CONFIG += staticlib # 指定为静态库(sharedlib为动态库)
TARGET = ui_module # 库文件名称(Windows:.lib/.dll,Linux:.a/.so,macOS:.a/.dylib)
DESTDIR = ./lib # 库文件输出目录
SOURCES += ui_widget.cpp
HEADERS += ui_widget.h
# 扩展:导出库的头文件路径(供其他子工程引用)
INCLUDEPATH += ./ui_module
2.3 条件编译
条件编译允许根据不同场景(如操作系统、Qt版本、自定义宏)编译不同代码,核心是DEFINES(定义宏)、CONFIG(配置项),以及contains/equals/greaterThan/lessThan等条件判断语法,补充更多实用示例和语法细节:
语法基础
| 语法 | 说明 | 示例 |
|---|---|---|
contains(VAR, VALUE) |
判断VAR是否包含VALUE | contains(DEFINES, ENABLE_LOG) |
equals(VAR, VALUE) |
判断VAR是否等于VALUE | equals(QT_MAJOR_VERSION, 6) |
greaterThan(VAR, VALUE) |
判断VAR是否大于VALUE | greaterThan(QT_VERSION, 5.15) |
lessThan(VAR, VALUE) |
判断VAR是否小于VALUE | lessThan(QT_VERSION, 6.0) |
win32/linux/macx |
操作系统专属条件(内置) | win32 { ... } |
示例1:定义自定义宏,控制功能开关
# 定义宏ENABLE_LOG(等价于C++中的#define ENABLE_LOG)
DEFINES += ENABLE_LOG
# 条件编译:如果定义了ENABLE_LOG,引入日志相关文件
contains(DEFINES, ENABLE_LOG) {
SOURCES += log_helper.cpp
HEADERS += log_helper.h
# 追加日志宏定义
DEFINES += LOG_LEVEL=3 # 3=DEBUG级别
} else {
DEFINES += LOG_LEVEL=1 # 1=ERROR级别
}
示例2:根据操作系统编译差异化代码
# Windows系统(win32包含32位/64位,win64可指定64位)
win32 {
# 引入Windows特有的库(-l表示链接库,user32是Windows系统库)
LIBS += -luser32 -lkernel32
# 定义Windows宏
DEFINES += OS_WINDOWS
# 设置Windows专属输出目录
DESTDIR = ./bin/win32
}
# Linux系统(linux包含x86/ARM等架构)
linux {
# 引入Linux特有的库(pthread是线程库)
LIBS += -lpthread -lrt
DEFINES += OS_LINUX
DESTDIR = ./bin/linux
}
# macOS系统
macx {
DEFINES += OS_MAC
# macOS专属编译选项
QMAKE_CXXFLAGS += -stdlib=libc++
DESTDIR = ./bin/macx
}
示例3:根据Qt版本编译差异化代码
# Qt6及以上版本
greaterThan(QT_MAJOR_VERSION, 5) {
DEFINES += QT6_VERSION
# Qt6移除的模块,替换为Qt Core5Compat
QT += core5compat
} else {
# Qt5版本
DEFINES += QT5_VERSION
# Qt5专属模块
QT += multimediawidgets
}
三、Qt窗口基类与内存管理
Qt的窗口开发基于三大核心基类(QMainWindow/QWidget/QDialog),且其独特的父子对象机制(基于QObject)简化了内存管理,同时窗口坐标系统是UI布局和交互的基础,以下补充各基类的核心函数原型和内存管理的细节。
3.1 三大窗口基类
3.1.1 QMainWindow
QMainWindow是带完整桌面应用框架的窗口类,内置菜单栏(QMenuBar)、工具栏(QToolBar)、状态栏(QStatusBar)、中心窗口(centralWidget),适合作为应用的主窗口。
核心函数原型
// 构造函数
QMainWindow::QMainWindow(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
// 菜单栏相关
// 获取/设置菜单栏(QMainWindow会接管菜单栏的内存)
QMenuBar *QMainWindow::menuBar() const;
void QMainWindow::setMenuBar(QMenuBar *menuBar);
// 工具栏相关
QToolBar *QMainWindow::addToolBar(const QString &title);
void QMainWindow::addToolBar(Qt::ToolBarArea area, QToolBar *toolbar);
void QMainWindow::removeToolBar(QToolBar *toolbar);
// 状态栏相关
QStatusBar *QMainWindow::statusBar() const;
void QMainWindow::setStatusBar(QStatusBar *statusBar);
// 中心窗口相关(QMainWindow必须设置中心窗口,否则空白区域无法响应事件)
void QMainWindow::setCentralWidget(QWidget *widget);
QWidget *QMainWindow::centralWidget() const;
// 窗口属性
void QMainWindow::setWindowTitle(const QString &title);
QString QMainWindow::windowTitle() const;
void QMainWindow::resize(int w, int h);
void QMainWindow::resize(const QSize &size);
void QMainWindow::show(); // 显示窗口(非模态)
代码示例:创建带菜单栏/工具栏/状态栏的QMainWindow
#include <QApplication>
#include <QMainWindow>
#include <QMenuBar>
#include <QMenu>
#include <QAction>
#include <QToolBar>
#include <QStatusBar>
#include <QLabel>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
// 创建主窗口(构造函数:父对象为nullptr,窗口标志为默认)
QMainWindow w(nullptr, Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint);
w.setWindowTitle("QMainWindow Demo");
w.resize(800, 600);
// 1. 创建菜单栏
QMenuBar *menuBar = w.menuBar();
QMenu *fileMenu = menuBar->addMenu("文件(&F)"); // &F表示快捷键Alt+F
QAction *newAction = fileMenu->addAction(QIcon(":/icons/new.png"), "新建(&N)"); // 带图标
QAction *openAction = fileMenu->addAction("打开(&O)");
fileMenu->addSeparator(); // 添加分隔线
QAction *exitAction = fileMenu->addAction("退出(&E)");
// 绑定退出信号与槽
QObject::connect(exitAction, &QAction::triggered, &a, &QApplication::quit);
// 2. 创建工具栏
QToolBar *toolBar = w.addToolBar("主工具栏");
toolBar->addAction(newAction); // 复用菜单栏的Action
toolBar->addAction(openAction);
// 3. 创建状态栏
QStatusBar *statusBar = w.statusBar();
statusBar->addWidget(new QLabel("就绪")); // 左侧提示
statusBar->addPermanentWidget(new QLabel("v1.0.0")); // 右侧永久显示
// 4. 设置中心窗口
QWidget *centralWidget = new QWidget(&w);
w.setCentralWidget(centralWidget);
w.show();
return a.exec();
}
示例代码运行效果展示:
3.1.2 QWidget
QWidget是通用的空白窗口类,是所有UI组件(包括QMainWindow、QDialog、QPushButton)的基类,支持自定义绘制、事件响应,适合作为自定义控件或简单窗口。
核心函数原型
// 构造函数
QWidget::QWidget(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
// 父对象管理(继承自QObject,重写以适配窗口层级)
void QWidget::setParent(QWidget *parent);
void QWidget::setParent(QWidget *parent, Qt::WindowFlags f);
QWidget *QWidget::parentWidget() const; // 获取父窗口,无则返回nullptr
// 窗口位置与尺寸
void QWidget::move(int x, int y); // 设置客户区左上角坐标(父窗口坐标系)
void QWidget::move(const QPoint &pos);
QPoint QWidget::pos() const; // 获取窗口左上角坐标(父窗口坐标系)
void QWidget::resize(int w, int h);
void QWidget::resize(const QSize &size);
QSize QWidget::size() const;
void QWidget::setGeometry(int x, int y, int w, int h); // 一次性设置位置+尺寸
QRect QWidget::geometry() const;
// 窗口显示与隐藏
void QWidget::show(); // 显示窗口(非模态)
void QWidget::hide(); // 隐藏窗口
bool QWidget::isVisible() const; // 判断是否可见
// 事件重写(自定义控件核心)
protected:
void QWidget::paintEvent(QPaintEvent *event); // 绘制事件(自定义绘制)
void QWidget::mousePressEvent(QMouseEvent *event); // 鼠标按下事件
void QWidget::keyPressEvent(QKeyEvent *event); // 键盘按下事件
void QWidget::resizeEvent(QResizeEvent *event); // 窗口大小变化事件
代码示例:创建带按钮的自定义QWidget
#include <QApplication>
#include <QWidget>
#include <QPushButton>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
// 创建空白窗口
QWidget w;
w.setWindowTitle("QWidget Demo");
w.resize(400, 300);
// 创建按钮(父对象为w,按钮会显示在w的窗口内)
QPushButton *btn = new QPushButton("点击我", &w);
// 设置按钮位置(绝对定位)
btn->move(150, 120);
w.show();
return a.exec();
}
示例代码运行效果展示:
3.1.3 QDialog
QDialog是对话框窗口类,用于临时交互(如提示、输入、选择),支持模态/非模态显示,内置对话框按钮盒(QDialogButtonBox),适合作为功能弹窗。
核心函数原型
// 构造函数
QDialog::QDialog(QWidget *parent = nullptr, Qt::WindowFlags f = Qt::WindowFlags());
// 显示模式(核心差异)
int QDialog::exec(); // 模态显示:阻塞主窗口,返回对话框结果(QDialog::Accepted/Rejected)
void QDialog::show(); // 非模态显示:不阻塞主窗口,独立显示
void QDialog::open(); // 半模态显示:阻塞主窗口,但允许事件循环处理(Qt5+)
// 对话框结果
void QDialog::setResult(int result);
int QDialog::result() const;
void QDialog::accept(); // 确认:设置result为Accepted,关闭对话框
void QDialog::reject(); // 取消:设置result为Rejected,关闭对话框
// 按钮盒(简化对话框按钮布局)
void QDialog::setDialogButtonBox(QDialogButtonBox *buttonBox);
QDialogButtonBox *QDialog::dialogButtonBox() const;
代码示例:创建带按钮盒的模态对话框
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QDialog>
#include <QLabel>
#include <QDialogButtonBox>
#include <QVBoxLayout>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QWidget w;
w.setWindowTitle("主窗口");
w.resize(400, 300);
QPushButton *btn = new QPushButton("打开对话框", &w);
btn->move(150, 120);
// 绑定按钮点击信号
QObject::connect(btn, &QPushButton::clicked, [&]() {
// 创建对话框(父对象为w,继承父窗口的样式)
QDialog dlg(&w, Qt::Dialog | Qt::WindowCloseButtonHint);
dlg.setWindowTitle("提示对话框");
dlg.resize(300, 150);
// 创建布局(避免绝对定位)
QVBoxLayout *layout = new QVBoxLayout(&dlg);
QLabel *label = new QLabel("是否确认执行该操作?", &dlg);
label->setAlignment(Qt::AlignCenter);
// 创建按钮盒(内置确认/取消按钮)
QDialogButtonBox *buttonBox = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel, &dlg);
// 绑定按钮信号
connect(buttonBox, &QDialogButtonBox::accepted, &dlg, &QDialog::accept);
connect(buttonBox, &QDialogButtonBox::rejected, &dlg, &QDialog::reject);
// 添加控件到布局
layout->addWidget(label);
layout->addWidget(buttonBox);
// 模态显示:阻塞主窗口,直到对话框关闭
int result = dlg.exec();
if (result == QDialog::Accepted) {
btn->setText("已确认");
} else {
btn->setText("已取消");
}
});
w.show();
return a.exec();
}
示例代码运行效果展示:

三大基类核心区别总结
| 类名 | 核心特性 | 适用场景 | 关键函数 |
|---|---|---|---|
| QMainWindow | 内置菜单栏/工具栏/状态栏,必须设置中心窗口 | 应用主窗口(如编辑器、浏览器主界面) | menuBar()/setCentralWidget() |
| QWidget | 通用空白窗口,所有控件的基类,支持自定义绘制 | 自定义控件、简单窗口、容器控件 | paintEvent()/setParent() |
| QDialog | 支持模态/非模态显示,内置按钮盒 | 临时交互弹窗(提示、输入、确认) | exec()/accept()/reject() |
3.2 父子对象机制(内存管理核心)
Qt的父子对象机制是基于QObject实现的内存管理方案,无需手动管理大部分对象的内存,核心规则补充具体实现细节和函数原型:
核心规则
- 当一个
QObject子类对象(如QWidget、QPushButton)设置了父对象:- 子对象会被加入父对象的“子对象列表”(
QObject::children()); - 父对象销毁时(析构函数),会遍历子对象列表,逐个调用
delete销毁所有子对象; - 子对象的生命周期由父对象管理,无需手动
delete。
- 子对象会被加入父对象的“子对象列表”(
- 手动删除子对象时:
- 子对象会自动从父对象的子对象列表中移除(避免父对象重复销毁);
- 触发
QObject::destroyed()信号,可用于监听子对象销毁。
- 栈对象作为子对象:
- 栈对象销毁时(如函数结束),会自动调用
setParent(nullptr)脱离父对象列表; - 父对象销毁时不会重复销毁栈对象,避免双重释放。
- 栈对象销毁时(如函数结束),会自动调用
核心函数原型
// 父对象设置
void QObject::setParent(QObject *parent);
QObject *QObject::parent() const; // 获取父对象(返回QObject*,需强转为QWidget*)
// 子对象管理
QList<QObject *> QObject::children() const; // 获取所有直接子对象
QObject *QObject::findChild(const QString &name, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const; // 查找子对象
QList<QObject *> QObject::findChildren(const QString &name, Qt::FindChildOptions options = Qt::FindChildrenRecursively) const;
// 销毁子对象
void QObject::deleteLater(); // 延迟销毁:将销毁操作加入事件循环,避免当前事件处理中销毁对象
bool QObject::destroyed(QObject *obj); // 信号:对象销毁时触发
代码示例:父子对象机制演示
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <qDebug>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
// 创建父对象(堆对象)
QWidget *w = new QWidget;
w->setWindowTitle("父子对象机制");
w->resize(400, 300);
w->setObjectName("MainWindow"); // 设置对象名,用于findChild
// 创建子对象1:构造函数指定父对象
QPushButton *btn1 = new QPushButton("按钮1", w);
btn1->setObjectName("Button1");
btn1->move(100, 100);
// 创建子对象2:手动设置父对象
QPushButton *btn2 = new QPushButton("按钮2");
btn2->setParent(w); // 调用QObject::setParent
btn2->move(200, 100);
// 演示:获取父对象的子对象列表
qDebug() << "父对象的子对象数量:" << w->children().size(); // 2
// 查找指定名称的子对象
QPushButton *findBtn = w->findChild<QPushButton*>("Button1");
if (findBtn) {
qDebug() << "找到子对象:" << findBtn->text(); // "按钮1"
}
w->show();
// 运行程序后关闭窗口,w被销毁时自动销毁btn1和btn2
int ret = a.exec();
delete w; // 销毁父对象,触发子对象销毁
qDebug() << "父对象已销毁,子对象自动销毁";
return ret;
}
示例代码运行效果展示:QObject_demo

常见坑点
- 避免循环父对象:A设置B为父对象,B又设置A为父对象,会导致析构时死循环;
deleteLater()的使用场景:在信号槽中销毁当前对象(如connect(btn, &QPushButton::clicked, this, &MyWidget::deleteLater)),避免直接delete this导致崩溃;- 动态创建的子对象:若未设置父对象,必须手动
delete,否则内存泄漏。
3.3 窗口坐标系统
Qt的坐标系统分为客户区坐标和全局坐标,补充坐标转换的函数原型和更具体的使用场景:
3.3.1 坐标类型
- 客户区坐标:
- 原点:窗口的左上角(不含标题栏、边框);
- 坐标系:x轴向右,y轴向下;
- 适用场景:控件在窗口内的定位、鼠标在窗口内的位置。
- 全局坐标:
- 原点:屏幕的左上角(多屏幕时,主屏幕为原点);
- 坐标系:x轴向右,y轴向下;
- 适用场景:多窗口交互、屏幕截图、鼠标全局位置。
3.3.2 坐标转换函数原型
// 客户区坐标 → 全局坐标
QPoint QWidget::mapToGlobal(const QPoint &pos) const;
// 全局坐标 → 客户区坐标
QPoint QWidget::mapFromGlobal(const QPoint &pos) const;
// 客户区坐标 → 父窗口坐标(父窗口的客户区)
QPoint QWidget::mapToParent(const QPoint &pos) const;
// 父窗口坐标 → 客户区坐标
QPoint QWidget::mapFromParent(const QPoint &pos) const;
// 客户区坐标 → 任意窗口坐标
QPoint QWidget::mapTo(const QWidget *parent, const QPoint &pos) const;
// 任意窗口坐标 → 客户区坐标
QPoint QWidget::mapFrom(const QWidget *parent, const QPoint &pos) const;
// 获取鼠标位置
QPoint QWidget::mapFromGlobal(const QPoint &globalPos) const; // 全局→当前窗口
QPoint QCursor::pos(); // 获取鼠标全局坐标(静态函数)
void QCursor::setPos(const QPoint &pos); // 设置鼠标全局坐标(静态函数)
代码示例:坐标转换与鼠标位置监听
#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QMouseEvent>
#include <qDebug>
class MyWidget : public QWidget {
Q_OBJECT
public:
MyWidget(QWidget *parent = nullptr) : QWidget(parent) {
setWindowTitle("坐标转换演示");
resize(400, 300);
btn = new QPushButton("点击查看坐标", this);
btn->move(150, 120);
// 绑定按钮点击:获取按钮的全局坐标
connect(btn, &QPushButton::clicked, this, [=]() {
QPoint btnLocalPos = btn->pos(); // 按钮在当前窗口的客户区坐标
QPoint btnGlobalPos = btn->mapToGlobal(btnLocalPos); // 转换为全局坐标
qDebug() << "按钮客户区坐标:" << btnLocalPos;
qDebug() << "按钮全局坐标:" << btnGlobalPos;
});
}
protected:
// 重写鼠标点击事件:获取鼠标坐标
void mousePressEvent(QMouseEvent *event) override {
// 1. 鼠标在当前窗口的客户区坐标
QPoint localPos = event->pos();
// 2. 转换为全局坐标
QPoint globalPos = mapToGlobal(localPos);
// 3. 全局坐标转回客户区坐标
QPoint localPos2 = mapFromGlobal(globalPos);
qDebug() << "鼠标客户区坐标:" << localPos;
qDebug() << "鼠标全局坐标:" << globalPos;
qDebug() << "转回客户区坐标:" << localPos2;
// 4. 获取鼠标全局坐标(静态函数)
QPoint cursorGlobalPos = QCursor::pos();
qDebug() << "鼠标全局坐标(QCursor):" << cursorGlobalPos;
}
private:
QPushButton *btn;
};
#include "main.moc" // moc工具生成的代码(处理Q_OBJECT宏)
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
MyWidget w;
w.show();
return a.exec();
}
示例代码运行效果展示:CoordinateConversion_MousePosListening

四、Qt核心数据类型
Qt在C++原生类型基础上封装了核心数据类型,解决了原生类型的跨平台、Unicode支持、易用性问题,其中QString和QVariant是最常用的两个,补充核心函数原型和更具体的使用场景。
4.1 QString
QString是Qt封装的Unicode字符串类型(基于UTF-16编码),解决了C++原生std::string不支持Unicode、接口繁琐的问题,补充核心函数原型和进阶用法。
核心函数原型
// 构造函数
QString::QString(); // 空字符串
QString::QString(const char *str); // 从C字符串(UTF-8)构造
QString::QString(const QString &other); // 拷贝构造
QString::QString(int size, QChar ch); // 构造指定长度、字符的字符串
// 字符串拼接
QString &QString::append(const QString &str); // 尾部追加
QString &QString::prepend(const QString &str); // 头部追加
QString QString::arg(const QString &a, int fieldWidth = 0, QChar fillChar = QLatin1Char(' ')) const; // 格式化替换
QString operator+(const QString &a, const QString &b); // 重载+运算符
// 类型转换
int QString::toInt(bool *ok = nullptr, int base = 10) const; // 转int(base为进制,默认10)
double QString::toDouble(bool *ok = nullptr) const; // 转double
float QString::toFloat(bool *ok = nullptr) const; // 转float
QByteArray QString::toUtf8() const; // 转UTF-8的QByteArray(C字符串用.data())
static QString QString::number(int n, int base = 10); // 静态函数:数值转字符串
static QString QString::number(double n, char format = 'g', int precision = 6); // 浮点数转字符串
static QString QString::fromUtf8(const char *str, int size = -1); // 从UTF-8 C字符串构造
// 查找/替换
int QString::indexOf(const QString &str, int from = 0, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; // 查找子串(返回索引,无则-1)
bool QString::contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; // 是否包含子串
QString &QString::replace(const QString &before, const QString &after, Qt::CaseSensitivity cs = Qt::CaseSensitive); // 替换子串
// 其他常用函数
int QString::length() const; // 字符串长度(字符数)
bool QString::isEmpty() const; // 是否为空(长度0)
bool QString::isNull() const; // 是否为null(仅默认构造的空字符串为null)
QString QString::trimmed() const; // 去除首尾空白字符
QString QString::simplified() const; // 去除首尾空白,中间多个空白替换为一个
代码示例:QString进阶用法
#include <QApplication>
#include <QString>
#include <qDebug>
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
// 1. 构造函数
QString str1; // 空字符串(isNull()=true,isEmpty()=true)
QString str2 = "Hello Qt"; // 从C字符串构造
QString str3(5, 'A'); // "AAAAA"
qDebug() << "str1是否为null:" << str1.isNull() << ",是否为空:" << str1.isEmpty();
// 2. 拼接(arg格式化推荐)
QString name = "张三";
int age = 25;
double score = 98.5;
QString info = QString("姓名:%1,年龄:%2,成绩:%3").arg(name).arg(age).arg(score, 0, 'f', 1);
qDebug() << "格式化信息:" << info; // "姓名:张三,年龄:25,成绩:98.5"
// 3. 类型转换(带错误处理)
QString numStr = "12345";
bool ok;
int num = numStr.toInt(&ok);
if (ok) {
qDebug() << "numStr转int:" << num;
} else {
qDebug() << "转换失败";
}
// 非法转换(含字母)
QString badStr = "12a3";
int badNum = badStr.toInt(&ok);
qDebug() << "badStr转int是否成功:" << ok << ",值:" << badNum; // ok=false,值=0
// 4. 查找/替换
QString str = "Qt is a cross-platform framework, Qt is powerful";
int firstIndex = str.indexOf("Qt"); // 0
int secondIndex = str.indexOf("Qt", firstIndex + 1); // 32
qDebug() << "Qt首次出现位置:" << firstIndex << ",第二次:" << secondIndex;
// 忽略大小写查找
int ignoreCaseIndex = str.indexOf("qt", 0, Qt::CaseInsensitive); // 0
qDebug() << "忽略大小写查找qt:" << ignoreCaseIndex;
// 替换所有Qt为Qt6
QString newStr = str.replace("Qt", "Qt6");
qDebug() << "替换后:" << newStr;
// 5. 去除空白
QString spaceStr = " Hello Qt ";
qDebug() << "trimmed:" << spaceStr.trimmed(); // "Hello Qt"
qDebug() << "simplified:" << spaceStr.simplified(); // "Hello Qt"
return a.exec();
}
示例代码运行效果展示:QString_demo

4.2 QVariant
QVariant是Qt的“万能类型”,可以存储几乎所有Qt基础类型(int、QString、QColor、QSize等)和自定义类型,解决了不同类型统一存储的问题(如容器中存储不同类型),补充核心函数原型和自定义类型支持。
核心函数原型
// 构造函数
QVariant::QVariant(); // 空类型
QVariant::QVariant(int val); // 存储int
QVariant::QVariant(const QString &val); // 存储QString
QVariant::QVariant(double val); // 存储double
template <typename T> QVariant::QVariant(const T &val); // 模板构造(支持自定义类型)
// 类型判断
const char *QVariant::typeName() const; // 获取类型名称(如"int"、"QString")
QVariant::Type QVariant::type() const; // 获取类型枚举(如QVariant::Int、QVariant::String)
bool QVariant::canConvert(QMetaType type) const; // 判断是否可转换为指定类型
// 类型转换
int QVariant::toInt(bool *ok = nullptr) const; // 转int
double QVariant::toDouble(bool *ok = nullptr) const; // 转double
QString QVariant::toString() const; // 转QString
template <typename T> T QVariant::value() const; // 模板函数:转指定类型(需注册元类型)
// 自定义类型支持(需注册)
static int qRegisterMetaType<T>(const char *typeName); // 注册自定义类型
代码示例:QVariant存储基础类型+自定义类型
#include <QApplication>
#include <QVariant>
#include <QString>
#include <QColor>
#include <qDebug>
// 自定义类型(需注册元类型)
struct User {
QString name;
int age;
// 必须重载<<运算符,否则qDebug无法输出
friend QDebug operator<<(QDebug debug, const User &user) {
debug << "User(name:" << user.name << ", age:" << user.age << ")";
return debug;
}
};
// 注册自定义类型(全局作用域)
Q_DECLARE_METATYPE(User)
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
// 1. 存储基础类型
QVariant var1(100); // int
QVariant var2("Qt Variant"); // C字符串→QString
QVariant var3(3.14); // double
QVariant var4(QColor(255, 0, 0)); // QColor
qDebug() << "var1类型:" << var1.typeName() << ",值:" << var1.toInt();
qDebug() << "var4类型:" << var4.typeName() << ",值:" << var4.value<QColor>().name(); // #ff0000
// 2. 存储自定义类型
User user = {"张三", 25};
QVariant var5 = QVariant::fromValue(user); // 存储自定义类型
qDebug() << "var5类型:" << var5.typeName() << ",值:" << var5.value<User>();
// 3. 转换失败处理
bool ok;
int val = var4.toInt(&ok); // QColor转int失败
qDebug() << "QColor转int是否成功:" << ok << ",值:" << val; // ok=false,值=0
return a.exec();
}
示例代码运行效果展示:QVariant_demo

五、Qt容器类
Qt提供了一套跨平台的容器类,替代C++标准容器(std::vector/std::map等),核心优势是线程安全(只读操作)、跨平台兼容、接口更易用,补充各容器的核心函数原型和效率优化建议。
5.1 容器类效率对比
| 容器类 | 底层实现 | 时间复杂度(核心操作) | 优势场景 | 劣势场景 |
|---|---|---|---|---|
| QList | 数组+指针(预分配内存) | 头部/尾部插入:O(1);随机访问:O(1);中间插入:O(n) | 高频头部/尾部插入、随机访问、轻量级元素(int/QString) | 大对象存储(拷贝成本高)、中间高频插入 |
| QVector | 动态数组(连续内存) | 随机访问:O(1);尾部插入:O(1)(预分配);中间插入:O(n) | 高频随机访问、少插入删除、数值类型存储 | 头部/中间高频插入 |
| QMap | 红黑树(有序) | 插入/查找/删除:O(log n) | 有序键值对、范围查找(如keys()/values()) | 高频插入删除(效率低于QHash) |
| QHash | 哈希表(无序) | 插入/查找/删除:平均O(1),最坏O(n) | 高频查找、无序键值对、大数据量存储 | 有序遍历、哈希冲突多的场景 |
5.2 核心容器用法示例
5.2.1 QList(最常用)
// 核心函数原型
// 构造函数
QList::QList(); // 空列表
QList::QList(const QList &other); // 拷贝构造
QList::QList(std::initializer_list<T> args); // 初始化列表构造(Qt5+)
// 插入/删除
void QList::append(const T &value); // 尾部插入
void QList::prepend(const T &value); // 头部插入
void QList::insert(int i, const T &value); // 索引i插入
T QList::takeAt(int i); // 删除索引i的元素并返回
void QList::removeAt(int i); // 删除索引i的元素(不返回)
void QList::clear(); // 清空列表
// 访问元素
T &QList::operator[](int i); // 读写访问(无越界检查)
const T &QList::at(int i) const; // 只读访问(有越界检查,更安全)
T &QList::first(); // 第一个元素
T &QList::last(); // 最后一个元素
// 查找/遍历
int QList::indexOf(const T &value, int from = 0) const; // 查找元素索引
bool QList::contains(const T &value) const; // 是否包含元素
// 迭代器
typedef typename QList::iterator iterator; // 可读写迭代器
typedef typename QList::const_iterator const_iterator; // 只读迭代器
iterator QList::begin();
iterator QList::end();
5.2.2 QVector
// 核心函数原型
// 构造函数
QVector::QVector(); // 空向量
QVector::QVector(int size); // 指定初始大小(元素默认构造)
QVector::QVector(int size, const T &value); // 指定初始大小和默认值
// 插入/删除
void QVector::append(const T &value); // 尾部插入
void QVector::push_back(const T &value); // 等价于append
void QVector::insert(int i, const T &value); // 索引i插入(效率低)
void QVector::remove(int i, int count = 1); // 从索引i删除count个元素
void QVector::resize(int size); // 调整大小(扩容/缩容)
// 访问元素
T &QVector::operator[](int i); // 读写访问
const T &QVector::at(int i) const; // 只读访问(越界检查)
int QVector::size() const; // 元素数量
int QVector::capacity() const; // 已分配内存的容量
void QVector::reserve(int size); // 预分配容量(减少扩容次数)
5.2.3 QMap与QHash
// QMap核心函数原型
// 构造函数
QMap::QMap(); // 空映射
QMap::QMap(const QMap &other); // 拷贝构造
// 插入/删除
QMap::iterator QMap::insert(const Key &key, const T &value); // 插入键值对(键重复则覆盖)
void QMap::remove(const Key &key); // 删除指定键的元素
void QMap::clear(); // 清空
// 查找/访问
T &QMap::operator[](const Key &key); // 读写访问(键不存在则插入默认值)
const T QMap::value(const Key &key, const T &defaultValue = T()) const; // 只读访问(无则返回默认值)
QMap::iterator QMap::find(const Key &key); // 查找键的迭代器
bool QMap::contains(const Key &key) const; // 是否包含键
// 遍历
QList<Key> QMap::keys() const; // 获取所有键(有序)
QList<T> QMap::values() const; // 获取所有值(有序)
// QHash核心函数原型(与QMap基本一致,差异:无序、哈希表实现)
QHash::QHash();
QHash::iterator QHash::insert(const Key &key, const T &value);
T QHash::value(const Key &key, const T &defaultValue = T()) const;
// 扩展:设置哈希桶数量(优化性能)
void QHash::reserve(int size);
int QHash::bucketCount() const;
5.3Qt容器类综合示例
聚焦最常用 4 种容器,演示增删改查、遍历、存储自定义类
#include <QCoreApplication>
#include <QList>
#include <QVector>
#include <QMap>
#include <QHash>
#include <QString>
#include <QDebug>
// 自定义类(演示容器存储自定义对象)
class Student {
public:
int id; // 学号
QString name; // 姓名
// 构造函数
Student(int i = 0, QString n = "") : id(i), name(n) {}
// 重载输出符,方便打印
friend QDebug operator<<(QDebug debug, const Student& s) {
debug << "Student{ id:" << s.id << ", name:" << s.name << " }";
return debug;
}
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
qDebug() << "========== Qt 四大常用容器 综合示例 ==========\n";
// ==================== 1. QList(最常用动态列表) ====================
qDebug() << "=== 1. QList 用法 ===";
QList<Student> stuList;
// 增
stuList << Student(101, "张三") << Student(102, "李四");
stuList.append(Student(103, "王五"));
// 查:访问、遍历
qDebug() << "QList第一个元素:" << stuList.first();
qDebug() << "QList全部元素:";
for (const auto& s : stuList) qDebug() << s;
// 改
stuList[1].name = "李四(修改)";
// 删
stuList.removeAt(0);
qDebug() << "删除后QList:" << stuList << "\n";
// ==================== 2. QVector(连续内存数组,高效随机访问) ====================
qDebug() << "=== 2. QVector 用法 ===";
QVector<int> scoreVec;
scoreVec << 90 << 85 << 95 << 88;
// 随机访问(效率最高)
qDebug() << "QVector索引2的值:" << scoreVec[2];
// 排序
std::sort(scoreVec.begin(), scoreVec.end());
qDebug() << "排序后QVector:" << scoreVec << "\n";
// ==================== 3. QMap(有序键值对,Key自动排序) ====================
qDebug() << "=== 3. QMap 用法 ===";
QMap<int, QString> classMap; // Key:班级号,Value:班级名
// 增
classMap[201] = "计算机1班";
classMap.insert(203, "计算机3班");
classMap.insert(202, "计算机2班");
// 自动按键排序
qDebug() << "QMap(自动排序):" << classMap;
// 查
qDebug() << "查找Key=202:" << classMap.value(202) << "\n";
// ==================== 4. QHash(哈希键值对,查询速度极快,无序) ====================
qDebug() << "=== 4. QHash 用法 ===";
QHash<QString, int> scoreHash; // Key:姓名,Value:分数
scoreHash["张三"] = 92;
scoreHash["李四"] = 87;
// 快速查找
qDebug() << "QHash查找张三分数:" << scoreHash["张三"];
qDebug() << "QHash所有键:" << scoreHash.keys();
return a.exec();
}
示例代码运行效果展示:QtContainer_demo

六、Qt常用工具类
Qt提供了一系列工具类,简化日常开发中的通用操作,补充核心函数原型和进阶用法。
6.1 QSize(尺寸类)
// 构造函数
QSize::QSize(); // (0,0)
QSize::QSize(int width, int height); // 指定宽高
// 尺寸操作
void QSize::setWidth(int width);
void QSize::setHeight(int height);
int QSize::width() const;
int QSize::height() const;
void QSize::scale(int width, int height, Qt::AspectRatioMode mode); // 缩放(保持宽高比)
void QSize::scale(const QSize &size, Qt::AspectRatioMode mode);
bool QSize::isEmpty() const; // 宽/高≤0则为true
bool QSize::isValid() const; // 宽/高≥0则为true
6.2 QDateTime(日期时间类)
// 构造函数
QDateTime::QDateTime(); // 无效时间
QDateTime::QDateTime(const QDate &date, const QTime &time, Qt::TimeSpec spec = Qt::LocalTime); // 日期+时间构造
// 静态函数:获取当前时间
static QDateTime QDateTime::currentDateTime(); // 本地时间
static QDateTime QDateTime::currentDateTimeUtc(); // UTC时间
// 格式化
QString QDateTime::toString(const QString &format) const; // 自定义格式
QString QDateTime::toString(Qt::DateFormat format = Qt::TextDate) const; // 预设格式
// 时间戳转换
qint64 QDateTime::toSecsSinceEpoch() const; // 秒级时间戳(1970-01-01 00:00:00 UTC)
qint64 QDateTime::toMSecsSinceEpoch() const; // 毫秒级时间戳
static QDateTime QDateTime::fromSecsSinceEpoch(qint64 secs, Qt::TimeSpec spec = Qt::LocalTime);
static QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec = Qt::LocalTime);
// 时间运算
QDateTime QDateTime::addDays(int days) const; // 加天数
QDateTime QDateTime::addSecs(int secs) const; // 加秒数
int QDateTime::daysTo(const QDateTime &other) const; // 计算与另一个时间的天数差
6.3 QFileInfo(文件信息类)
// 构造函数
QFileInfo::QFileInfo(); // 空文件信息
QFileInfo::QFileInfo(const QString &filePath); // 指定文件路径构造
QFileInfo::QFileInfo(const QFile &file); // 从QFile构造
// 路径信息
QString QFileInfo::fileName() const; // 文件名(含扩展名)
QString QFileInfo::baseName() const; // 基础名(不含扩展名)
QString QFileInfo::suffix() const; // 扩展名(不含.)
QString QFileInfo::filePath() const; // 相对路径
QString QFileInfo::absoluteFilePath() const; // 绝对路径
QString QFileInfo::path() const; // 目录路径(不含文件名)
// 文件属性
qint64 QFileInfo::size() const; // 文件大小(字节)
bool QFileInfo::isFile() const; // 是否为普通文件
bool QFileInfo::isDir() const; // 是否为目录
bool QFileInfo::isSymLink() const; // 是否为符号链接
bool QFileInfo::exists() const; // 文件是否存在
QDateTime QFileInfo::birthTime() const; // 创建时间
QDateTime QFileInfo::lastModified() const; // 最后修改时间
QDateTime QFileInfo::lastRead() const; // 最后访问时间
6.4Qt 常用工具类 综合示例
#include <QCoreApplication>
#include <QString> // 字符串工具(最核心)
#include <QDateTime> // 日期时间
#include <QTimer> // 定时器
#include <QFile> // 文件读写
#include <QDir> // 目录操作
#include <QRandomGenerator> // 随机数
#include <QDebug>
#include <QObject>
// 自定义工具类(封装所有Qt常用工具,演示类的用法)
class QtToolDemo : public QObject {
Q_OBJECT
public:
explicit QtToolDemo(QObject *parent = nullptr) : QObject(parent) {
qDebug() << "========== Qt 常用工具类 综合示例 ==========\n";
testString(); // 1. QString 字符串工具
testDateTime(); // 2. 日期时间工具
testRandom(); // 3. 随机数工具
testFileDir(); // 4. 文件/目录工具
testTimer(); // 5. 定时器工具
}
private:
// 1. QString:Qt最核心字符串工具(替代char*,支持中文、编码、拼接)
void testString() {
qDebug() << "=== 1. QString 字符串工具 ===";
QString str = "Hello Qt";
// 常用操作:拼接、替换、分割、格式化
str.append(" 工具类");
str.replace("Qt", "QT");
qDebug() << "拼接替换后:" << str;
qDebug() << "字符串分割:" << str.split(" ");
qDebug() << "格式化字符串:" << QString("学号:%1,姓名:%2").arg(1001).arg("张三") << "\n";
}
// 2. QDateTime:日期、时间、时间差计算
void testDateTime() {
qDebug() << "=== 2. QDateTime 日期时间工具 ===";
QDateTime now = QDateTime::currentDateTime();
qDebug() << "当前时间:" << now.toString("yyyy-MM-dd hh:mm:ss");
// 时间计算:加1天
QDateTime nextDay = now.addDays(1);
qDebug() << "明天此时:" << nextDay.toString("yyyy-MM-dd") << "\n";
}
// 3. QRandomGenerator:安全随机数
void testRandom() {
qDebug() << "=== 3. 随机数工具 ===";
int randNum = QRandomGenerator::global()->bounded(1, 100); // 1-99随机数
qDebug() << "1-99随机数:" << randNum << "\n";
}
// 4. QFile + QDir:文件读写、目录创建
void testFileDir() {
qDebug() << "=== 4. 文件/目录工具 ===";
QDir dir;
// 创建目录
if (!dir.exists("TestDir")) dir.mkdir("TestDir");
// 写入文件
QFile file("TestDir/test.txt");
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
file.write("Qt工具类测试文件\n");
file.close();
}
// 读取文件
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
qDebug() << "文件内容:" << file.readAll();
file.close();
}
qDebug() << "";
}
// 5. QTimer:单次/循环定时器
void testTimer() {
qDebug() << "=== 5. QTimer 定时器工具 ===";
QTimer *timer = new QTimer(this);
// 1秒后执行一次
timer->singleShot(1000, this, [=]() {
qDebug() << "定时器触发:1秒倒计时完成!";
});
}
};
// 信号槽兼容(Qt类必须)
#include "main.moc"
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 创建自定义工具类对象,自动运行所有示例
QtToolDemo demo;
return a.exec();
}
示例代码运行效果展示:QtUtility_demo

引用出处
本文核心理论概念、知识点框架参考自爱编程的大丙老师的Qt博客:
- Qt 入门
- Qt 中的基础数据类型
- Qt官方文档:Qt 6.6 Documentation
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)