目录
一. 核心数据类型 (Core Datatypes)
二. 文件和目录 (File and Directory Handling)
三. 事件系统 (Event System)
QObject
QCoreApplication
QEventLoop
QEvent
QTimer
QMetaObject:
运行时类型信息 (RTTI)
信号与槽连接
属性系统
动态方法调用
类型转换
自我检查
四. 多线程和并发 (Multithreading and Concurrency)
五. 国际化和本地化 (Internationalization and Localization)
六. 进程和进程间通信 (Process and Inter-Process Communication - IPC)
七. 插件支持 (Plugin Support)
八. 文本编解码 (Text Codecs)
九. 动态库加载 (Dynamic Library Loading)
十. 全局函数
十一. 其他实用工具
请跳转章节,此处不再重复:QT核心模块QtCore功能详细说明,并给出测试代码(一)
请跳转章节,此处不再重复:QT核心模块QtCore功能详细说明,并给出测试代码(二)
请跳转章节,此处不再重复:QT核心模块QtCore功能详细说明,并给出测试代码(三)
QCoreApplication
是 Qt 应用程序的核心类,负责 管理应用程序的生命周期,并 提供事件循环 (Event Loop)。所有 Qt 程序(无论是 GUI 还是控制台应用)都必须有一个 QCoreApplication
或 QGuiApplication/QApplication
实例。唯一实例(Singleton)
exec()
方法:启动事件循环
exec()
,应用程序就会进入事件循环,开始监听和处理事件。exec()
运行期间,应用程序会保持活动状态,响应各种事件。quit()
和 exit()
方法
quit()
方法用于正常地退出事件循环。它会发出 aboutToQuit()
信号,然后将事件循环的退出码设置为 0。exit(int returnCode)
方法也可以用于退出事件循环,并且可以指定一个自定义的退出码。exec()
方法因为调用了 quit()
或 exit()
而结束时,它会返回应用程序的退出码。main()
函数中,你都需要创建 QCoreApplication
(或 QApplication
对于 GUI 程序)的实例。QCoreApplication
会初始化 Qt 的核心功能,例如信号和槽机制、事件系统等。QCoreApplication
实例之后,但在调用 exec()
之前执行一些应用程序特定的初始化操作。exec()
方法后,应用程序进入事件循环,开始正常运行,响应各种事件。quit()
或 exit()
时,事件循环结束。QCoreApplication
会发出 aboutToQuit()
信号。main()
函数在 exec()
返回后继续执行,通常会返回 exec()
的返回值作为应用程序的退出码。aboutToQuit()
: 在事件循环即将结束时发出。这是进行最后清理工作的理想时机。applicationStateChanged()
: 当应用程序的状态发生改变时发出。setApplicationName(const QString &name)
/ applicationName()
: 设置或获取应用程序的名称。setApplicationVersion(const QString &version)
/ applicationVersion()
: 设置或获取应用程序的版本号。setOrganizationName(const QString &name)
/ organizationName()
: 设置或获取组织的名称。setOrganizationDomain(const QString &domain)
/ organizationDomain()
: 设置或获取组织的域名。arguments()
返回一个 QStringList
,包含应用程序的名称以及所有传递给它的命令行参数。applicationState()获取【
QGuiApplication 或 QApplication】
Qt::ApplicationState
枚举值
Qt::ApplicationActive
, Qt::ApplicationInactive
Qt::ApplicationHidden
QCoreApplication 相关的静态函数
函数 | 作用 |
---|---|
arguments() |
获取命令行参数 |
applicationName() / setApplicationName() |
获取/设置应用程序名称 |
applicationVersion() |
获取应用程序版本 |
quit() |
退出应用程序(安全) |
exit(int code) |
退出事件循环 |
processEvents() |
手动处理事件队列 |
postEvent(QObject *receiver, QEvent *event) |
向对象发送事件 |
QCoreApplication VS QApplication
类 | 适用场景 | 特点 |
---|---|---|
QCoreApplication |
控制台程序、非 GUI 程序 | 只提供 基本事件循环,不支持 GUI |
QGuiApplication |
需要 GUI(但无 QWidget) | 提供 事件循环 + GUI 相关功能(如 OpenGL, QML) |
QApplication |
标准 GUI 应用 | 提供 完整 GUI 支持(包含 QGuiApplication 的所有功能) |
测试代码-QCoreApplication
#include
#include
#include
#include
int main(int argc, char *argv[]) {
// 创建 QCoreApplication 实例
QCoreApplication app(argc, argv);
// ======================
// 1. 实例化 QCoreApplication
// ======================
qDebug() << "1. QCoreApplication instance created.";
// ======================
// 2. 生命周期管理 - aboutToQuit() 信号
// ======================
QObject::connect(&app, &QCoreApplication::aboutToQuit, []() {
qDebug() << "2. QCoreApplication::aboutToQuit() signal emitted before exiting.";
});
// ======================
// 3. 命令行参数
// ======================
qDebug() << "\n3. Command Line Arguments:";
QStringList args = app.arguments();
for (int i = 0; i < args.size(); ++i) {
qDebug() << " Argument" << i << ":" << args[i];
}
// ======================
// 4. 应用程序名称及其他全局信息
// ======================
app.setApplicationName("MyAppTest");
app.setApplicationVersion("1.0.0");
app.setOrganizationName("MyOrganization");
app.setOrganizationDomain("myorganization.com");
qDebug() << "\n4. Application Info:";
qDebug() << " Application Name:" << app.applicationName();
qDebug() << " Application Version:" << app.applicationVersion();
qDebug() << " Organization Name:" << app.organizationName();
qDebug() << " Organization Domain:" << app.organizationDomain();
// ======================
// 5. 获取 QCoreApplication 实例
// ======================
qDebug() << "\n5. QCoreApplication Instance:";
QCoreApplication *instancePtr = QCoreApplication::instance();
qDebug() << " Address of app object:" << &app;
qDebug() << " Address of QCoreApplication::instance():" << instancePtr;
qDebug() << " Are they the same instance?" << (&app == instancePtr);
// ======================
// 6. 退出应用程序
// ======================
qDebug() << "\n6. Exiting the application in 5 seconds...";
QTimer::singleShot(5000, &app, &QCoreApplication::quit);
// ======================
// 7. 启动事件循环
// ======================
qDebug() << "\n7. Calling app.exec() to start the event loop...";
int returnCode = app.exec();
qDebug() << "8. app.exec() finished with return code:" << returnCode;
return returnCode;
}
// ======================
// console
// ======================
//1. QCoreApplication instance created.
//3. Command Line Arguments:
// Argument 0 : "/home/user/QtProj/build-QtCore-Desktop-Debug/QtCore"
//4. Application Info:
// Application Name: "MyAppTest"
// Application Version: "1.0.0"
// Organization Name: "MyOrganization"
// Organization Domain: "myorganization.com"
//5. QCoreApplication Instance:
// Address of app object: QCoreApplication(0x7fffffffe120)
// Address of QCoreApplication::instance(): QCoreApplication(0x7fffffffe120)
// Are they the same instance? true
//6. Exiting the application in 5 seconds...
//7. Calling app.exec() to start the event loop...
//2. QCoreApplication::aboutToQuit() signal emitted before exiting.
//8. app.exec() finished with return code: 0
QEventLoop 是 Qt 框架中的一个核心类,用于管理和运行事件循环。它是 QCoreApplication 事件循环机制的基础,提供了灵活的事件处理能力,适用于需要自定义事件循环或局部事件处理的场景。
QEventLoop
的核心功能,通过 exec()
方法启动,持续监听和处理事件。
通过 exec() 方法启动一个事件循环,类似于 QCoreApplication::exec() 的底层实现。
调用 exec() 后,线程进入阻塞状态,循环从事件队列中取出事件并分发,事件循环依赖平台特定的事件调度器(如 Linux 的 epoll、Windows 的消息循环)。
可通过信号或手动调用控制循环的启动和停止
操作系统事件: 在 GUI 应用中,处理窗口事件(如鼠标、键盘)。
定时器事件: QTimer 的 timeout 信号。
信号: 通过 QueuedConnection 传递的跨线程信号。
帖子事件: 通过 QCoreApplication::postEvent() 手动添加的事件。
Socket 和 File Notifiers: QSocketNotifier 和 QFileSystemWatcher 的事件。
自定义事件: 继承 QEvent 创建的用户定义事件。
应用程序级别:使用 QCoreApplication::installEventFilter()。对象级别:使用 QObject::installEventFilter()。
过滤器对象在事件分发前接收事件,可选择处理或忽略。
事件流:产生->创建->投递/发送->检索->过滤->分发->处理->传播 (GUI)->消亡
QEventLoop 将事件分发给目标对象,通常通过调用目标的 event() 方法。
事件队列中的每个事件都有目标 QObject,调用 QObject::event(),由目标对象处理或转发到特定事件处理函数。
可通过重写 event() 方法自定义分发逻辑。
QEventLoop 支持嵌套运行,即在一个事件循环中启动另一个局部事件循环。
每个 QEventLoop 实例独立管理其退出条件,嵌套循环不会干扰外层循环。
在处理复杂操作(如模态对话框、同步等待)时使用。
通过 processEvents() 方法,QEventLoop 可以在不阻塞线程的情况下处理事件队列。
只处理当前队列中的事件,不会等待新事件。
用于刷新状态或避免 UI 冻结。
processEvents事件类型
QEventLoop::AllEvents
(默认值): 处理所有类型的挂起事件。QEventLoop::ExcludeUserInputEvents
: 处理所有挂起的事件,但不包括用户输入事件(例如,鼠标和键盘事件)。QEventLoop::ExcludeSocketNotifiers
: 处理所有挂起的事件,但不包括来自套接字通知器的事件。QEventLoop::ExcludeTimers
: 处理所有挂起的事件,但不包括定时器事件。QEventLoop::ExcludeDeferredDDeletions
: 处理所有挂起的事件,但不包括延迟删除事件(由 deleteLater()
触发)。QEventLoop::ExcludeDeferredUpdates
: 处理所有挂起的事件,但不包括延迟样式更新事件。QEventLoop::ExcludeApplicationExiting
: 处理所有挂起的事件,但不包括应用程序退出事件。一个 QEventLoop
实例在哪个线程中运行,它就负责处理该线程中的事件。
每个线程可以独立地拥有自己的事件循环。
quit(): 设置退出标志,返回值为 0。
exit(int): 设置退出标志并指定返回值。
功能: wakeUp() 方法从其他线程唤醒事件循环,确保处理新事件。
机制: 发送一个唤醒信号给事件循环线程,使其检查队列。
在多线程中通知事件循环处理新加入的事件。
QEventLoop 与 QCoreApplication 关系
QCoreApplication::exec()
:启动了应用程序的主事件循环。
QCoreApplication
隐式的 创建和管理QEventLoop
QEventLoop
对象是真正处理事件:等待事件、获取事件、事件过滤、事件分发。
QEventLoop
的生命周期通常与 QCoreApplication
的 exec()
调用绑定在一起。
主事件循环由 QCoreApplication::exec()
启动,可添加额外的 QEventLoop
事件循环。
QEventLoop 子事件循环常见应用场景
应用场景 | 描述 |
---|---|
模态对话框 (QDialog ) |
进入子事件循环,阻塞主窗口交互,直到用户关闭对话框: QDialog dialog; |
等待子线程任务完成 | 在主线程等待子线程完成,避免 UI 冻结 QEventLoop loop; |
避免 UI 冻结的耗时任务 | 在循环中使用 QEventLoop loop; |
同步等待网络请求完成 |
QEventLoop loop; |
消息框 (QMessageBox ) |
QMessageBox msgBox; |
测试代码-事件循环
#include
#include
#include
#include
#include
#include
#include
// ======================
// CustomEvent 类定义
// ======================
class CustomEvent : public QEvent {
public:
CustomEvent() : QEvent(QEvent::Type(QEvent::User + 1)) {}
};
// ======================
// EventHandler 类定义
// ======================
class EventHandler : public QObject {
Q_OBJECT
public:
EventHandler() {}
protected:
// 重写 event 方法,处理自定义事件和定时器事件
bool event(QEvent *e) override {
if (e->type() == QEvent::Type(QEvent::User + 1)) {
qDebug() << "Custom event received in event().";
return true;
} else if (e->type() == QEvent::Timer) {
qDebug() << "Timer event handled in event().";
return true;
}
return QObject::event(e);
}
// 重写 eventFilter 方法,过滤定时器事件
bool eventFilter(QObject *obj, QEvent *event) override {
if (event->type() == QEvent::Timer) {
qDebug() << "Timer event filtered before reaching target.";
return true; // 过滤掉定时器事件
}
return QObject::eventFilter(obj, event);
}
};
// ======================
// WorkerThread 类定义
// ======================
class WorkerThread : public QThread {
Q_OBJECT
public:
WorkerThread() : loop(nullptr) {}
QEventLoop *loop;
protected:
// 重写 run 方法,启动线程的事件循环
void run() override {
loop = new QEventLoop();
QTimer timer;
timer.start(1000);
QObject::connect(&timer, &QTimer::timeout, []() {
qDebug() << "Thread timer triggered in:" << QThread::currentThreadId();
});
qDebug() << "Thread event loop starting in:" << QThread::currentThreadId();
loop->exec();
qDebug() << "Thread event loop exited.";
delete loop;
}
};
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
qDebug() << "Main thread ID:" << QThread::currentThreadId();
// ======================
// 1. 启动和管理事件循环
// ======================
qDebug() << "\n1. Starting and Managing Event Loop";
QEventLoop mainLoop;
QTimer exitTimer;
exitTimer.setSingleShot(true);
QObject::connect(&exitTimer, &QTimer::timeout, &mainLoop, &QEventLoop::quit);
exitTimer.start(10000); // 10秒后退出主循环
// ======================
// 2. 处理来自各种来源的事件
// ======================
qDebug() << "\n2. Handling Events from Various Sources";
QTimer timer;
timer.start(1000); // 定时器事件
QObject::connect(&timer, &QTimer::timeout, []() {
qDebug() << "Timer event triggered.";
});
QSocketNotifier notifier(STDIN_FILENO, QSocketNotifier::Read); // Socket Notifier 事件
QObject::connect(¬ifier, &QSocketNotifier::activated, []() {
// qDebug() << "Input detected on stdin.";
});
EventHandler handler;
QCoreApplication::postEvent(&handler, new CustomEvent()); // 帖子事件(自定义事件)
// ======================
// 3. 事件过滤
// ======================
qDebug() << "\n3. Event Filtering";
timer.installEventFilter(&handler); // 安装事件过滤器
// ======================
// 4. 事件分发
// ======================
qDebug() << "\n4. Event Dispatching";
// 通过 handler 的 event() 方法处理事件(见上文 CustomEvent)
// ======================
// 5. 支持嵌套事件循环
// ======================
qDebug() << "\n5. Nested Event Loop";
QTimer nestedTrigger;
nestedTrigger.start(2000);
QObject::connect(&nestedTrigger, &QTimer::timeout, [&mainLoop]() {
qDebug() << "Starting nested event loop...";
QEventLoop nestedLoop;
QTimer nestedTimer;
nestedTimer.setSingleShot(true);
QObject::connect(&nestedTimer, &QTimer::timeout, []() {
qDebug() << "Nested timer triggered.";
});
QObject::connect(&nestedTimer, &QTimer::timeout, &nestedLoop, &QEventLoop::quit);
nestedTimer.start(500);
nestedLoop.exec();
qDebug() << "Nested event loop finished.";
});
// ======================
// 6. 非阻塞的事件处理
// ======================
qDebug() << "\n6. Non-blocking Event Processing";
QTimer nonBlockingTimer;
nonBlockingTimer.start(1500);
QObject::connect(&nonBlockingTimer, &QTimer::timeout, []() {
qDebug() << "Non-blocking timer triggered.";
});
for (int i = 0; i < 3; ++i) {
qDebug() << "Processing events non-blocking...";
mainLoop.processEvents(QEventLoop::AllEvents, 1000); // 处理 1 秒内的事件
}
// ======================
// 7. 线程关联性
// ======================
qDebug() << "\n7. Thread Affinity";
WorkerThread thread;
thread.start();
// ======================
// 8. 控制事件循环的生命周期
// ======================
qDebug() << "\n8. Controlling Event Loop Lifecycle";
QEventLoop controlLoop;
QTimer controlTimer;
controlTimer.setSingleShot(true);
QObject::connect(&controlTimer, &QTimer::timeout, [&controlLoop]() {
qDebug() << "Exiting control loop with code 42.";
controlLoop.exit(42);
});
controlTimer.start(1000);
int result = controlLoop.exec();
qDebug() << "Control loop exited with code:" << result;
// ======================
// 9. 唤醒事件循环
// ======================
qDebug() << "\n9. Waking Up Event Loop";
QTimer wakeTimer;
wakeTimer.setSingleShot(true);
QObject::connect(&wakeTimer, &QTimer::timeout, [&thread]() {
if (thread.loop && thread.loop->isRunning()) {
qDebug() << "Waking up thread event loop...";
thread.loop->wakeUp();
QCoreApplication::postEvent(thread.loop, new CustomEvent());
}
});
wakeTimer.start(3000);
// ======================
// 启动主事件循环
// ======================
qDebug() << "\nStarting main event loop...";
mainLoop.exec();
thread.quit();
thread.wait();
return 0;
}
#include "main.moc" // 包含 moc 生成的文件
// ======================
// console
// ======================
//Main thread ID: 0x7ffff50757c0
//1. Starting and Managing Event Loop
//2. Handling Events from Various Sources
//3. Event Filtering
//4. Event Dispatching
//5. Nested Event Loop
//6. Non-blocking Event Processing
//Processing events non-blocking...
//Custom event received in event().
//Processing events non-blocking...
//Processing events non-blocking...
//7. Thread Affinity
//8. Controlling Event Loop Lifecycle
//Thread event loop starting in: 0x7ffff5066640
//Timer event filtered before reaching target.
//Exiting control loop with code 42.
//Control loop exited with code: 42
//9. Waking Up Event Loop
//Starting main event loop...
//Thread timer triggered in: 0x7ffff5066640
//Non-blocking timer triggered.
//Starting nested event loop...
//Timer event filtered before reaching target.
//Thread timer triggered in: 0x7ffff5066640
//Nested timer triggered.
//Nested event loop finished.
//Non-blocking timer triggered.
//Timer event filtered before reaching target.
//Thread timer triggered in: 0x7ffff5066640
//Starting nested event loop...
//Timer event filtered before reaching target.
//Waking up thread event loop...
//Thread timer triggered in: 0x7ffff5066640
//Non-blocking timer triggered.
//Nested timer triggered.
//Nested event loop finished.
//Thread timer triggered in: 0x7ffff5066640
//Timer event filtered before reaching target.
//Thread timer triggered in: 0x7ffff5066640
//Starting nested event loop...
//Non-blocking timer triggered.
//Timer event filtered before reaching target.
//Nested timer triggered.
//Nested event loop finished.
//Timer event filtered before reaching target.
//Thread timer triggered in: 0x7ffff5066640
//Non-blocking timer triggered.
//Starting nested event loop...
//Timer event filtered before reaching target.
//Thread timer triggered in: 0x7ffff5066640
//Nested timer triggered.
//Nested event loop finished.
//Non-blocking timer triggered.
//Timer event filtered before reaching target.
//Thread timer triggered in: 0x7ffff5066640
//Starting nested event loop...
//Timer event filtered before reaching target.
//Thread timer triggered in: 0x7ffff5066640
//Non-blocking timer triggered.
//Nested timer triggered.
//Nested event loop finished.
//Thread event loop exited.
QEvent 是 Qt 框架中所有事件类的基类。在 Qt 中,事件是代表应用程序内部或由于外部活动而发生的事情的对象。它们是 Qt 应用程序中实现交互性和响应性的核心机制。
基本概念:
QEvent
或其子类的实例来表示该事件。鼠标点击、键盘输入等;QEvent::Type
枚举定义。进行事件区分处理;QObject
及其子类(通常是窗口部件 QWidget
)。这个目标对象负责处理该事件并做出相应的响应。主要作用:
事件处理流程:
event()
函数来直接传递。QCoreApplication::postEvent()
将事件发布到事件队列中,稍后由主事件循环处理。QCoreApplication::sendEvent()
同步地将事件发送给目标对象,该函数会立即处理事件。QWidget
)会接收到事件,并通常在其 event()
函数中进行处理。例如:
mousePressEvent()
处理鼠标按下事件 (QMouseEvent
).keyPressEvent()
处理键盘按下事件 (QKeyEvent
).paintEvent()
处理绘制事件 (QPaintEvent
).resizeEvent()
处理窗口大小调整事件 (QResizeEvent
).closeEvent()
处理窗口关闭事件 (QCloseEvent
). 子类通常会重写这些特定的事件处理函数来响应相应的事件。QObject::installEventFilter()
安装事件过滤器。常见事件
类名 | 描述 |
---|---|
QMouseEvent |
鼠标事件(按下、释放、移动、双击等) |
QKeyEvent |
键盘事件(按下、释放) |
QPaintEvent |
窗口部件需要被绘制或重绘的事件 |
QResizeEvent |
窗口部件大小改变的事件 |
QMoveEvent |
窗口部件位置移动的事件 |
QCloseEvent |
窗口部件关闭的事件 |
QTimerEvent |
由 QTimer 发出的定时器事件 |
QFocusEvent |
窗口部件获得或失去键盘焦点的事件 |
QActionEvent |
与 QAction 相关的事件(例如,触发) |
QContextMenuEvent |
上下文菜单事件 |
QDragEnterEvent |
拖放操作相关的事件 |
QDragMoveEvent |
拖放操作相关的事件 |
QDropEvent |
拖放操作相关的事件 |
QShowEvent |
窗口部件显示的事件 |
QHideEvent |
窗口部件隐藏的事件 |
QWindowStateChangeEvent |
窗口部件窗口状态改变的事件(例如,最大化、最小化) |
QCustomEvent |
用户自定义的事件类型 |
QEvent::Type
常量
常量名 | 描述 |
---|---|
QEvent::None |
空事件。 |
QEvent::MouseButtonPress |
鼠标按键按下。 |
QEvent::MouseButtonRelease |
鼠标按键释放。 |
QEvent::MouseMove |
鼠标移动。 |
QEvent::KeyPress |
键盘按键按下。 |
QEvent::KeyRelease |
键盘按键释放。 |
QEvent::Timer |
定时器到期。 |
QEvent::Paint |
需要重绘部件。 |
QEvent::Close |
窗口关闭请求。 |
QEvent::Resize |
部件大小改变。 |
QEvent::Move |
部件位置移动。 |
QEvent::Show |
部件显示。 |
QEvent::Hide |
部件隐藏。 |
QEvent::FocusIn |
部件获得焦点。 |
QEvent::FocusOut |
部件失去焦点。 |
QEvent::InputMethod |
输入法相关事件。 |
QEvent::SockAct |
套接字活动。 |
QEvent::FileOpen |
文件打开请求。 |
QEvent::Quit |
应用程序退出。 |
QEvent::User |
用户自定义事件类型的起始值。开发者可以定义大于或等于 QEvent::User 的值作为自定义事件类型。 |
测试代码-QEvent
#include
#include
#include
#include
// ======================
// 1. 定义自定义事件类型
// ======================
const QEvent::Type CustomEventType = static_cast(QEvent::User + 1);
// ======================
// 2. 定义自定义事件类
// ======================
class MyCustomEvent : public QEvent {
public:
MyCustomEvent() : QEvent(CustomEventType) {}
QString message = "Hello from Custom Event!";
};
// ======================
// 3. 自定义对象,用于演示事件处理
// ======================
class EventHandlingObject : public QObject {
Q_OBJECT
public:
explicit EventHandlingObject(QObject *parent = nullptr) : QObject(parent) {}
protected:
// 重写 event 方法,处理自定义事件
bool event(QEvent *event) override {
if (event->type() == CustomEventType) {
MyCustomEvent *customEvent = static_cast(event);
qDebug() << "EventHandlingObject: Received Custom Event - " << customEvent->message;
return true;
}
return QObject::event(event);
}
// 重写 timerEvent 方法,处理定时器事件
void timerEvent(QTimerEvent *event) override {
qDebug() << "EventHandlingObject: Timer event with ID:" << event->timerId();
QObject::timerEvent(event);
}
};
// ======================
// 4. 应用程序级别事件过滤器
// ======================
class ApplicationEventFilter : public QObject {
protected:
// 重写 eventFilter 方法,过滤自定义事件和定时器事件
bool eventFilter(QObject *watched, QEvent *event) override {
if (event->type() == CustomEventType) {
qDebug() << "ApplicationEventFilter: Received Custom Event on" << watched;
} else if (event->type() == QEvent::Timer) {
QTimerEvent *timerEvent = static_cast(event);
qDebug() << "ApplicationEventFilter: Timer event on" << watched << " with ID:" << timerEvent->timerId();
}
return QObject::eventFilter(watched, event);
}
};
// ======================
// 5. 对象级别事件过滤器
// ======================
class ObjectEventFilter : public QObject {
Q_OBJECT
public:
explicit ObjectEventFilter(EventHandlingObject *target, QObject *parent = nullptr)
: QObject(parent), targetObj(target) {}
protected:
// 重写 eventFilter 方法,过滤自定义事件
bool eventFilter(QObject *watched, QEvent *event) override {
if (watched == targetObj && event->type() == CustomEventType) {
qDebug() << "ObjectEventFilter (Handler): Received Custom Event";
}
return QObject::eventFilter(watched, event);
}
private:
EventHandlingObject *targetObj; // 目标对象
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 创建事件处理对象
EventHandlingObject handler;
// ======================
// 安装应用程序级别事件过滤器
// ======================
ApplicationEventFilter appFilter;
a.installEventFilter(&appFilter);
// ======================
// 安装对象级别事件过滤器
// ======================
ObjectEventFilter *objFilter = new ObjectEventFilter(&handler);
handler.installEventFilter(objFilter);
// ======================
// 创建并启动定时器,定期发送自定义事件
// ======================
QTimer customEventTimer;
QObject::connect(&customEventTimer, &QTimer::timeout, [&handler]() {
MyCustomEvent *customEvent = new MyCustomEvent();
QCoreApplication::postEvent(&handler, customEvent);
});
customEventTimer.start(2000);
// ======================
// 启动另一个定时器,发送标准的 QTimerEvent
// ======================
QTimer standardTimer;
QObject::connect(&standardTimer, &QTimer::timeout, [&]() {
qDebug() << "main: Timer2 timeout - standard QTimerEvent will be generated.";
});
standardTimer.start(3000);
// ======================
// 启动应用程序事件循环
// ======================
qDebug() << "Starting application event loop...";
return a.exec();
}
#include "main.moc" // 包含 moc 生成的文件
// ======================
// console
// ======================
//Starting application event loop...
//ApplicationEventFilter: Timer event on QTimer(0x7fffffffe0e0) with ID: 1
//ApplicationEventFilter: Received Custom Event on EventHandlingObject(0x7fffffffe0c0)
//ObjectEventFilter (Handler): Received Custom Event
//EventHandlingObject: Received Custom Event - "Hello from Custom Event!"
//ApplicationEventFilter: Timer event on QTimer(0x7fffffffe100) with ID: 2
//main: Timer2 timeout - standard QTimerEvent will be generated.
//ApplicationEventFilter: Timer event on QTimer(0x7fffffffe0e0) with ID: 1
//ApplicationEventFilter: Received Custom Event on EventHandlingObject(0x7fffffffe0c0)
//ObjectEventFilter (Handler): Received Custom Event
//EventHandlingObject: Received Custom Event - "Hello from Custom Event!"
//ApplicationEventFilter: Timer event on QTimer(0x7fffffffe0e0) with ID: 1
//ApplicationEventFilter: Timer event on QTimer(0x7fffffffe100) with ID: 2
//main: Timer2 timeout - standard QTimerEvent will be generated.
QTimer
类是 Qt 框架中用于实现定时功能的类。它允许您在指定的时间间隔后发出一个信号 (timeout()
),从而触发相应的操作。
核心功能与工作原理
QTimer
的主要功能是在设定的时间间隔结束后,自动发出 timeout()
信号。QTimer
的工作完全依赖于 Qt 的事件循环。QTimer
不会阻塞您的应用程序。 主要方法
timeout()
信号: 这是 QTimer
最重要的信号。start(int interval)
: 启动定时器,并设置时间间隔 interval
,单位是毫秒。stop()
: 停止定时器。setInterval(int interval)
: 设置定时器的时间间隔,单位是毫秒。interval() const
: 返回当前定时器的时间间隔(毫秒)。isSingleShot() const
: 返回一个布尔值,指示定时器是否为单次触发模式。setSingleShot(bool singleShot)
: 设置定时器是否为单次触发模式。
singleShot
为 true
,定时器在第一次 timeout()
信号发出后会自动停止。singleShot
为 false,
调用 stop()停止
。isActive() const
: 返回一个布尔值,指示定时器是否正在运行。singleShot(int msec, const QObject *receiver, const char *member)
: 这是一个方便的静态函数,用于创建并启动一个单次触发的定时器。定时器精度: QTimer
的精度取决于操作系统和系统的负载。
与 QThread::sleep()
的区别
QTimer
(非阻塞): 使用 QTimer
时,您的应用程序仍然可以响应其他事件(例如用户输入),因为定时器的工作依赖于事件循环。QThread::sleep()
(阻塞): 调用 QThread::sleep()
会使当前线程暂停执行指定的时间,期间应用程序无法响应任何事件,导致界面冻结。使用场景
用途 | 描述 |
---|---|
周期性更新 UI | 例如,每隔一段时间更新显示的时间、动画的帧等。 |
延迟执行操作 | 例如,在用户完成某个操作后延迟一段时间再执行下一步。 |
实现超时机制 | 例如,在等待网络响应时设置一个超时时间。 |
轮询数据 | 例如,定期检查服务器是否有新的数据。 |
动画效果 | 通过定时器不断触发重绘事件来创建动画效果。 |
测试代码-QTimer
#include
#include
#include
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
// ======================
// 单次触发定时器示例
// ======================
qDebug() << "--- 单次触发定时器示例 ---";
QTimer::singleShot(3000, []() {
qDebug() << "3 秒后执行一次!";
});
qDebug() << "单次触发定时器已启动,将在 3 秒后输出消息。";
// ======================
// 重复触发定时器示例
// ======================
qDebug() << "\n--- 重复触发定时器示例 ---";
int counter = 0;
QTimer *repeatingTimer = new QTimer(); // 使用 new 创建,避免局部变量在 lambda 中失效
QObject::connect(repeatingTimer, &QTimer::timeout, [&]() {
qDebug() << "每隔 1 秒触发一次,当前计数:" << ++counter;
if (counter >= 3) {
repeatingTimer->stop();
qDebug() << "重复触发定时器已停止。";
QTimer::singleShot(100, [&]() { // 稍作延迟后退出,确保输出完整
QCoreApplication::quit();
});
}
});
repeatingTimer->start(1000); // 设置时间间隔为 1000 毫秒 (1 秒)
qDebug() << "重复触发定时器已启动,每隔 1 秒输出消息,计数到 3 次后停止。";
// ======================
// 启动应用程序事件循环
// ======================
return app.exec();
}
// ======================
// console
// ======================
//--- 单次触发定时器示例 ---
//单次触发定时器已启动,将在 3 秒后输出消息。
//--- 重复触发定时器示例 ---
//重复触发定时器已启动,每隔 1 秒输出消息,计数到 3 次后停止。
//每隔 1 秒触发一次,当前计数: 1
//每隔 1 秒触发一次,当前计数: 2
//3 秒后执行一次!
//每隔 1 秒触发一次,当前计数: 3
//重复触发定时器已停止。
QMetaObject
类是 Qt 框架中元对象系统的核心组成部分。它提供了对 Qt 类在运行时进行自省的能力,使得 Qt 能够实现诸如信号与槽、属性系统、动态属性、以及对象序列化等高级特性。
类名 (Class Name)
QMetaObject
存储了类的完整名称。QMetaObject::className()
方法可以获取到这个名称。父类 (Parent Class)
QMetaObject
包含一个指向其直接父类的 QMetaObject
对象的指针。QMetaObject::superClass()
方法可以获取到父类的 QMetaObject
。3. 信号 (Signals)
QMetaObject
存储了以下信息:
QMetaObject::signalCount()
, QMetaObject::signal(int index)
, QMetaObject::indexOfSignal()
4. 槽 (Slots)
QMetaObject
存储了以下信息:
public
、protected
还是 private
。QMetaObject::slotCount()
, QMetaObject::slot(int index)
,QMetaObject::indexOfSlot()
属性 (Properties)
Q_PROPERTY
宏声,QMetaObject
存储了以下信息:
READ
方法指定)。WRITE
方法指定)。NOTIFY
信号,则存储该信号的元方法索引。QMetaObject::propertyCount()
QMetaObject::property(int index)
QMetaObject::indexOfProperty()
方法 (Methods)
Q_INVOKABLE
宏QMetaObject
存储了以下信息:
Q_INVOKABLE
方法。QMetaObject::methodCount()
QMetaObject::method(int index)
QMetaObject::indexOfMethod()
枚举 (Enums)
enum
或 enum class
,QMetaObject
存储了以下信息:
Q_FLAG
宏标记,一个可以进行位运算的标志类型。QMetaObject::enumeratorCount()
, QMetaObject::enumerator(int index)
, QMetaObject::indexOfEnumerator()
测试代码-运行时类型信息
#include
#include
#include
#include
#include
#include
#include
#include
// ======================
// MyClass 类定义
// ======================
class MyClass : public QObject {
Q_OBJECT
public:
enum MyEnum {
Value1 = 1,
Value2 = 2,
Value3 = 4
};
Q_ENUM(MyEnum)
Q_PROPERTY(int myProperty READ getMyProperty WRITE setMyProperty NOTIFY myPropertyChanged)
explicit MyClass(QObject *parent = nullptr) : QObject(parent), m_myProperty(0) {}
int getMyProperty() const { return m_myProperty; }
void setMyProperty(int value) {
if (m_myProperty != value) {
m_myProperty = value;
emit myPropertyChanged(m_myProperty);
}
}
public slots:
void mySlot(int value) {
qDebug() << "MySlot received:" << value;
}
void anotherSlot(const QString& text) {
qDebug() << "AnotherSlot received:" << text;
}
void overloadedSlot(int value) {
qDebug() << "OverloadedSlot (int) received:" << value;
}
void overloadedSlot(const QString& text) {
qDebug() << "OverloadedSlot (QString) received:" << text;
}
Q_INVOKABLE void myMethod(bool flag) {
qDebug() << "MyMethod called with flag:" << flag;
}
signals:
void mySignal(QString message);
void anotherSignal(int code, bool status);
void myPropertyChanged(int newValue);
private:
int m_myProperty; // 属性值
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 实例化 MyClass
MyClass obj;
const QMetaObject *metaObject = obj.metaObject(); // 使用实例的 metaObject
// ======================
// 1. 类名
// ======================
qDebug() << "--- 类名 ---";
qDebug() << "Class Name:" << metaObject->className();
// ======================
// 2. 父类
// ======================
qDebug() << "\n--- 父类 ---";
if (metaObject->superClass()) {
qDebug() << "Super Class Name:" << metaObject->superClass()->className();
} else {
qDebug() << "No super class.";
}
// ======================
// 3. 信号列表 Qt 4
// ======================
qDebug() << "\n--- 信号列表 ---";
int signalCount = 0;
for (int i = 0; i < metaObject->methodCount(); ++i) {
if (metaObject->method(i).methodType() == QMetaMethod::Signal) {
signalCount++;
}
}
qDebug() << "Number of Signals:" << signalCount;
for (int i = 0; i < metaObject->methodCount(); ++i) {
QMetaMethod method = metaObject->method(i);
if (method.methodType() == QMetaMethod::Signal) {
qDebug() << " Index:" << i << ", Name:" << method.name() << ", Signature:" << method.methodSignature();
}
}
// ======================
// 4. 槽列表
// ======================
int slotCount = 0;
for (int i = 0; i < metaObject->methodCount(); ++i) {
if (metaObject->method(i).methodType() == QMetaMethod::Slot) {
slotCount++;
}
}
qDebug() << "Number of Slots:" << slotCount;
for (int i = 0; i < metaObject->methodCount(); ++i) {
QMetaMethod method = metaObject->method(i);
if (method.methodType() == QMetaMethod::Slot) {
qDebug() << " Index:" << i << ", Name:" << method.name() << ", Signature:" << method.methodSignature();
}
}
// ======================
// 5. 属性列表
// ======================
qDebug() << "\n--- 属性列表 ---";
int propertyCount = metaObject->propertyCount();
qDebug() << "Number of Properties:" << propertyCount;
for (int i = 0; i < propertyCount; ++i) {
QMetaProperty property = metaObject->property(i);
qDebug() << " Index:" << i << ", Name:" << property.name() << ", Type:" << property.typeName()
<< ", Readable:" << property.isReadable() << ", Writable:" << property.isWritable();
}
// ======================
// 6. 方法列表
// ======================
qDebug() << "\n--- 方法列表 ---";
int methodCount = metaObject->methodCount();
qDebug() << "Number of Methods:" << methodCount;
for (int i = 0; i < methodCount; ++i) {
QMetaMethod method = metaObject->method(i);
QString type;
// if (method.methodType() == QMetaMethod::Method)
{
qDebug() << " Index:" << i << ", Type:" << method.methodType() << ", Name:" << method.name() << ", Signature:" << method.methodSignature();
}
}
// ======================
// 7. 枚举列表
// ======================
qDebug() << "\n--- 枚举列表 ---";
int enumCount = metaObject->enumeratorCount();
qDebug() << "Number of Enums:" << enumCount;
for (int i = 0; i < enumCount; ++i) {
QMetaEnum metaEnum = metaObject->enumerator(i);
qDebug() << " Name:" << metaEnum.name() << ", Scope:" << metaEnum.scope();
qDebug() << " Keys and Values:";
for (int j = 0; j < metaEnum.keyCount(); ++j) {
qDebug() << " " << metaEnum.key(j) << "=" << metaEnum.value(j);
}
}
// ======================
// 8. 测试功能
// ======================
qDebug() << "\n--- 测试功能 ---";
obj.setMyProperty(42); // 测试属性
QObject::connect(&obj, &MyClass::mySignal, &obj, &MyClass::anotherSlot);
emit obj.mySignal("Test Signal"); // 测试信号和槽
QTimer::singleShot(1000, [&obj]() {
obj.myMethod(true); // 测试 Q_INVOKABLE 方法
QCoreApplication::quit(); // 1 秒后退出
});
// ======================
// 启动应用程序事件循环
// ======================
return a.exec();
}
#include "main.moc" // 包含 moc 生成的文件
// ======================
// console
// ======================
//--- 类名 ---
//Class Name: MyClass
//--- 父类 ---
//Super Class Name: QObject
//--- 信号列表 ---
//Number of Signals: 6
// Index: 0 , Name: "destroyed" , Signature: "destroyed(QObject*)"
// Index: 1 , Name: "destroyed" , Signature: "destroyed()"
// Index: 2 , Name: "objectNameChanged" , Signature: "objectNameChanged(QString)"
// Index: 5 , Name: "mySignal" , Signature: "mySignal(QString)"
// Index: 6 , Name: "anotherSignal" , Signature: "anotherSignal(int,bool)"
// Index: 7 , Name: "myPropertyChanged" , Signature: "myPropertyChanged(int)"
//Number of Slots: 7
// Index: 3 , Name: "deleteLater" , Signature: "deleteLater()"
// Index: 4 , Name: "_q_reregisterTimers" , Signature: "_q_reregisterTimers(void*)"
// Index: 8 , Name: "mySlot" , Signature: "mySlot(int)"
// Index: 9 , Name: "anotherSlot" , Signature: "anotherSlot(QString)"
// Index: 10 , Name: "overloadedSlot" , Signature: "overloadedSlot(int)"
// Index: 11 , Name: "overloadedSlot" , Signature: "overloadedSlot(QString)"
// Index: 12 , Name: "myMethod" , Signature: "myMethod(bool)"
//--- 属性列表 ---
//Number of Properties: 2
// Index: 0 , Name: objectName , Type: QString , Readable: true , Writable: true
// Index: 1 , Name: myProperty , Type: int , Readable: true , Writable: true
//--- 方法列表 ---
//Number of Methods: 13
// Index: 0 , Type: 1 , Name: "destroyed" , Signature: "destroyed(QObject*)"
// Index: 1 , Type: 1 , Name: "destroyed" , Signature: "destroyed()"
// Index: 2 , Type: 1 , Name: "objectNameChanged" , Signature: "objectNameChanged(QString)"
// Index: 3 , Type: 2 , Name: "deleteLater" , Signature: "deleteLater()"
// Index: 4 , Type: 2 , Name: "_q_reregisterTimers" , Signature: "_q_reregisterTimers(void*)"
// Index: 5 , Type: 1 , Name: "mySignal" , Signature: "mySignal(QString)"
// Index: 6 , Type: 1 , Name: "anotherSignal" , Signature: "anotherSignal(int,bool)"
// Index: 7 , Type: 1 , Name: "myPropertyChanged" , Signature: "myPropertyChanged(int)"
// Index: 8 , Type: 2 , Name: "mySlot" , Signature: "mySlot(int)"
// Index: 9 , Type: 2 , Name: "anotherSlot" , Signature: "anotherSlot(QString)"
// Index: 10 , Type: 2 , Name: "overloadedSlot" , Signature: "overloadedSlot(int)"
// Index: 11 , Type: 2 , Name: "overloadedSlot" , Signature: "overloadedSlot(QString)"
// Index: 12 , Type: 2 , Name: "myMethod" , Signature: "myMethod(bool)"
//--- 枚举列表 ---
//Number of Enums: 1
// Name: MyEnum , Scope: MyClass
// Keys and Values:
// Value1 = 1
// Value2 = 2
// Value3 = 4
//--- 测试功能 ---
//AnotherSlot received: "Test Signal"
//MyMethod called with flag: true
运行时通过名称连接信号和槽
QMetaObject
包含了信号和槽的参数类型信息。connect()
会在运行时检查信号的参数类型是否与槽的参数类型兼容。connect()
函数会获取发送者和接收者的 QMetaObject
对象。QObject
都有一个线程亲缘性,它属于创建它的线程,或者通过 moveToThread()
移动到的线程。Qt::QueuedConnection
,Qt 就不会直接调用槽函数。QMetaObject
中存储的关于信号的信息(包括信号的名称和参数类型),将信号的参数值封装成一个事件 (event)。QCoreApplication::postEvent()
完成。QEventLoop
)。QMetaCallEvent
时,它会使用接收者对象的 QMetaObject
中的信息,找到对应的槽函数,并在接收者线程的上下文中执行 (invoke) 该槽函数,并将事件中携带的参数传递给槽函数。Q_PROPERTY
宏声明属性
DataType
: 属性的数据类型。Name
: 属性的名称,在运行时通过这个名称访问属性。READ getterMethod
: 指定用于获取属性值的成员函数(通常是 const
的)。WRITE setterMethod
(可选): 指定用于设置属性值的成员函数。NOTIFY signal
(可选): 指定当属性值改变时会发出的信号。QObject::property(const char *name) const
:
QMetaObject
会查找具有该名称的属性的元数据。READ
方法(getter)来获取属性的当前值。QVariant
对象,该对象封装了属性的值。QObject::setProperty(const char *name, const QVariant &value)
:
QVariant
对象作为参数。QMetaObject
会查找具有该名称的属性的元数据。value
的类型是否与属性的类型兼容。WRITE
方法(setter)来设置属性的新值。NOTIFY
信号,setProperty
方法通常会在成功设置属性值后发出该信号,通知其他对象属性已发生更改。QObject::metaObject()
获取对象的 QMetaObject
。QMetaObject::propertyCount()
获取属性的总数。QMetaObject::property(int index)
获取指定索引的 QMetaProperty
对象,该对象包含了属性的名称、类型、是否可读写等信息。QMetaObject::indexOfProperty(const char *name)
获取指定名称属性的索引测试代码-属性系统
#include
#include
#include
#include
#include
#include
// ======================
// MyClass 类定义
// ======================
class MyClass : public QObject {
Q_OBJECT
// 定义属性
Q_PROPERTY(int age READ getAge WRITE setAge NOTIFY ageChanged)
Q_PROPERTY(QString name READ getName WRITE setName NOTIFY nameChanged)
Q_PROPERTY(double score READ getScore WRITE setScore) // 无通知信号
public:
explicit MyClass(QObject *parent = nullptr) : QObject(parent), m_age(0), m_score(0.0) {}
// age 属性
int getAge() const { return m_age; }
void setAge(int value) {
if (m_age != value) {
m_age = value;
emit ageChanged(m_age);
}
}
// name 属性
QString getName() const { return m_name; }
void setName(const QString &value) {
if (m_name != value) {
m_name = value;
emit nameChanged(m_name);
}
}
// score 属性
double getScore() const { return m_score; }
void setScore(double value) { m_score = value; }
signals:
void ageChanged(int newAge);
void nameChanged(const QString &newName);
private:
int m_age; // 年龄属性
QString m_name; // 姓名属性
double m_score; // 分数属性
};
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
// 创建对象
MyClass obj;
// 获取元对象
const QMetaObject *metaObject = obj.metaObject();
// ======================
// 1. 打印属性信息
// ======================
qDebug() << "--- 属性列表 ---";
int propertyCount = metaObject->propertyCount();
qDebug() << "Number of Properties:" << propertyCount;
for (int i = 0; i < propertyCount; ++i) {
QMetaProperty property = metaObject->property(i);
qDebug() << " Index:" << i
<< ", Name:" << property.name()
<< ", Type:" << property.typeName()
<< ", Readable:" << property.isReadable()
<< ", Writable:" << property.isWritable()
<< ", Has Notify:" << property.hasNotifySignal();
if (property.hasNotifySignal()) {
qDebug() << " Notify Signal:" << property.notifySignal().methodSignature();
}
}
// ======================
// 2. 测试属性读写
// ======================
qDebug() << "\n--- 测试属性读写 ---";
// 设置初始值
obj.setAge(25);
obj.setName("Alice");
obj.setScore(95.5);
// 通过 QMetaProperty 读取属性
QMetaProperty ageProp = metaObject->property(metaObject->indexOfProperty("age"));
QMetaProperty nameProp = metaObject->property(metaObject->indexOfProperty("name"));
QMetaProperty scoreProp = metaObject->property(metaObject->indexOfProperty("score"));
qDebug() << "Initial Values:";
qDebug() << " Age:" << ageProp.read(&obj).toInt();
qDebug() << " Name:" << nameProp.read(&obj).toString();
qDebug() << " Score:" << scoreProp.read(&obj).toDouble();
// 通过 QMetaProperty 修改属性
ageProp.write(&obj, 30);
nameProp.write(&obj, "Bob");
scoreProp.write(&obj, 88.0);
qDebug() << "After Modification:";
qDebug() << " Age:" << ageProp.read(&obj).toInt();
qDebug() << " Name:" << nameProp.read(&obj).toString();
qDebug() << " Score:" << scoreProp.read(&obj).toDouble();
// ======================
// 3. 测试通知信号
// ======================
qDebug() << "\n--- 测试通知信号 ---";
QObject::connect(&obj, &MyClass::ageChanged, [](int newAge) {
qDebug() << "Signal: ageChanged emitted with value:" << newAge;
});
QObject::connect(&obj, &MyClass::nameChanged, [](const QString &newName) {
qDebug() << "Signal: nameChanged emitted with value:" << newName;
});
obj.setAge(35); // 触发 ageChanged 信号
obj.setName("Charlie"); // 触发 nameChanged 信号
obj.setScore(99.0); // 无信号
// ======================
// 退出程序
// ======================
QTimer::singleShot(1000, &app, &QCoreApplication::quit);
return app.exec();
}
#include "main.moc" // 包含 moc 生成的文件
// ======================
// console
// ======================
//--- 属性列表 ---
//Number of Properties: 4
// Index: 0 , Name: objectName , Type: QString , Readable: true , Writable: true , Has Notify: true
// Notify Signal: "objectNameChanged(QString)"
// Index: 1 , Name: age , Type: int , Readable: true , Writable: true , Has Notify: true
// Notify Signal: "ageChanged(int)"
// Index: 2 , Name: name , Type: QString , Readable: true , Writable: true , Has Notify: true
// Notify Signal: "nameChanged(QString)"
// Index: 3 , Name: score , Type: double , Readable: true , Writable: true , Has Notify: false
//--- 测试属性读写 ---
//Initial Values:
// Age: 25
// Name: "Alice"
// Score: 95.5
//After Modification:
// Age: 30
// Name: "Bob"
// Score: 88
//--- 测试通知信号 ---
//Signal: ageChanged emitted with value: 35
//Signal: nameChanged emitted with value: "Charlie"
QMetaObject::invokeMethod()
函数
object
(QObject):* 指向要调用方法的对象。method
(const char):* 要调用的方法的名称。type
(Qt::ConnectionType): 指定调用类型:
Qt::AutoConnection:自动选择
Qt::DirectConnection
: 立即在调用者的线程中执行。Qt::QueuedConnection
: 跨线程队列。Qt::BlockingQueuedConnection
: 阻塞调用Qt::UniqueConnection
: 唯一的连接。ret
(QGenericReturnArgument): 用于接收方法返回值的参数。returnVal
(QVariant): 接受 QVariant
类型的返回值。val0
到 val9
(QGenericArgument 或 QVariant): 最多可以传递 10 个参数。函数返回 true
如果方法被成功调用,否则返回 false
。
QMetaObject::invokeMethod()
工作流程
QMetaObject
对象。T
: 目标指针类型,您希望将 obj
转换成的类型。obj
: 要进行类型转换的 QObject
指针。T
类型指针或返回 nullptr
。QMetaObject::cast()
的工作原理
T
的 QMetaObject
对象(通常通过 T::staticMetaObject
)。QObject
指针 obj
获取其 QMetaObject
对象 (obj->metaObject()
).obj
的 QMetaObject
继承链(通过 superClass()
方法),检查在链中是否存在与目标类型 T
的 QMetaObject
相同的对象。QMetaObject
,则说明 obj
指向的对象是类型 T
或其派生类的一个实例,可以安全地转换为 T*
。QMetaObject
,则转换是不安全的,cast()
返回 nullptr
。上转型 (Upcasting) 和下转型 (Downcasting)
测试代码-类型转换
#include
#include
#include
// ======================
// Base 类定义
// ======================
class Base : public QObject {
Q_OBJECT
public:
explicit Base(QObject *parent = nullptr) : QObject(parent) {}
virtual void baseFunction() {
qDebug() << "Base: baseFunction called";
}
};
// ======================
// Derived 类定义
// ======================
class Derived : public Base {
Q_OBJECT
public:
explicit Derived(QObject *parent = nullptr) : Base(parent) {}
void derivedFunction() {
qDebug() << "Derived: derivedFunction called";
}
void baseFunction() override {
qDebug() << "Derived: baseFunction (overridden) called";
}
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
// 创建基类和派生类对象
Base baseObj;
Derived derivedObj;
// ======================
// 1. 上转型 (Derived* -> Base*) - 总是安全的
// ======================
Derived *derivedPtr = &derivedObj;
Base *upcastedPtr = qobject_cast (derivedPtr);
qDebug() << "--- Upcasting ---";
qDebug() << "Derived pointer:" << derivedPtr;
if (upcastedPtr) {
qDebug() << "Upcasting successful. Base pointer:" << upcastedPtr;
upcastedPtr->baseFunction(); // 调用重写后的方法(多态性)
} else {
qDebug() << "Upcasting failed (should not happen).";
}
// ======================
// 2. 下转型 (Base* -> Derived*) - 成功的情况
// ======================
Base *basePtr1 = &derivedObj; // 基类指针指向派生类对象
Derived *downcastedPtr1 = qobject_cast(basePtr1);
qDebug() << "\n--- Downcasting (Successful) ---";
qDebug() << "Base pointer:" << basePtr1;
if (downcastedPtr1) {
qDebug() << "Downcasting successful. Derived pointer:" << downcastedPtr1;
downcastedPtr1->derivedFunction(); // 调用派生类特有方法
downcastedPtr1->baseFunction(); // 调用重写后的方法
} else {
qDebug() << "Downcasting failed.";
}
// ======================
// 3. 下转型 (Base* -> Derived*) - 失败的情况
// ======================
Base *basePtr2 = &baseObj; // 基类指针指向基类对象
Derived *downcastedPtr2 = qobject_cast(basePtr2);
qDebug() << "\n--- Downcasting (Failed) ---";
qDebug() << "Base pointer:" << basePtr2;
if (downcastedPtr2) {
qDebug() << "Downcasting successful (should not happen). Derived pointer:" << downcastedPtr2;
downcastedPtr2->derivedFunction();
} else {
qDebug() << "Downcasting failed (as expected).";
}
return 0; // 无需事件循环,直接退出
}
#include "main.moc" // 包含 moc 生成的文件
// ======================
// console
// ======================
//--- Upcasting ---
//Derived pointer: Derived(0x7fffffffe130)
//Upcasting successful. Base pointer: Derived(0x7fffffffe130)
//Derived: baseFunction (overridden) called
//--- Downcasting (Successful) ---
//Base pointer: Derived(0x7fffffffe130)
//Downcasting successful. Derived pointer: Derived(0x7fffffffe130)
//Derived: derivedFunction called
//Derived: baseFunction (overridden) called
//--- Downcasting (Failed) ---
//Base pointer: Base(0x7fffffffe120)
//Downcasting failed (as expected).
QMetaObject
对象
obj->metaObject()
方法来获取指向该对象所属类的 QMetaObject
的指针。ClassName::staticMetaObject
来获取该类的 QMetaObject
对象。获取类名:使用 className()
方法获取类的名称(返回 const char*
):
获取信号列表(Qt 4)
signalCount()
方法获取类中定义的信号总数。signal(int index)
方法获取指定索引处的信号的元数据,返回一个 QMetaMethod
对象。name()
方法获取信号的名称, methodSignature()
方法获取包含参数类型的完整签名。indexOfSignal(const QByteArray &signalSignature)
方法可以通过信号签名查找其索引。获取槽列表(Qt 4)
slotCount()
方法获取类中定义的槽函数总数。slot(int index)
方法获取指定索引处的槽函数的元数据,返回一个 QMetaMethod
对象。name()
方法获取槽函数的名称, methodSignature()
方法获取包含参数类型的完整签名。indexOfSlot(const QByteArray &slotSignature)
方法可以通过槽函数签名查找其索引。获取方法列表 (包括信号和槽)
methodCount()
方法获取类中定义的所有方法(包括信号、槽和普通的 Q_INVOKABLE
方法)的总数。method(int index)
方法获取指定索引处的方法的元数据,返回一个 QMetaMethod
对象。name()
方法获取方法的名称,使用 methodType()
方法获取方法的类型(QMetaMethod::Signal
, QMetaMethod::Slot
, QMetaMethod::Method
)。
注:部分接口可能有更新!!!
QThread
QThread
提供了线程管理的功能,允许开发者创建和管理线程。
同步工具QMutex、QReadWriteLock、QSemaphore、QWaitCondition
QMutex:互斥锁,确保线程安全。
QReadWriteLock:读写锁,适用于多读少写场景。
QSemaphore:信号量,控制资源访问。
QWaitCondition:线程等待条件。
QThreadPool 和 QRunnable
线程池管理。
原子操作
QAtomicInt 和 QAtomicPointer 提供线程安全的原子操作。
QtConcurrent
QtConcurrent
提供了对并行计算的高层次抽象。它允许开发者简洁地进行多线程任务处理,如并行遍历、过滤等操作。
QLocale
QLocale
类用于管理语言、区域设置等本地化信息,能够根据不同的区域设置显示日期、时间、数字等格式。
QTranslator
QTranslator
用于加载翻译文件,以便将应用程序界面翻译成不同的语言。
QProcess
QProcess
类用于启动外部进程并与其进行交互,支持进程输入输出流的管理。
QLocalSocket, QLocalServer
QLocalSocket
: 本地套接字,用于与本地进程进行通信。
QLocalServer
: 本地服务器,用于监听来自其他进程的连接请求。
QSharedMemory
QSharedMemory
提供了进程间共享内存的访问,允许多个进程共享同一块内存区域。
QPluginLoader
QPluginLoader
用于加载动态插件,使得应用程序能够在运行时加载和卸载插件。
QFactoryInterface
QFactoryInterface
是插件接口,插件可以实现特定功能,并通过该接口供应用程序使用。
QTextCodec
QTextCodec
用于文本编码和解码,支持多种字符集,如 UTF-8、GBK、ISO-8859-1 等。
QLibrary
QLibrary
用于加载动态链接库,并提供访问其导出函数的能力,支持跨平台的动态库管理。
qAbs
计算绝对值。
qDebug、qWarning、qCritical
调试和日志输出。
qInstallMsgHandler
安装消息处理程序。
qVersion
返回 Qt 版本。
qRegisterResourceData 和 qUnregisterResourceData:
资源数据管理。
QUrl
URL 解析和生成。
QRandomGenerator
线程安全的随机数生成。
QCryptographicHas
加密哈希类(如 MD5、SHA-256)。
QJsonDocument、QJsonArray、QJsonObject、QJsonValue
JSON 处理:
QRegularExpression
Perl 兼容的正则表达式。
QSettings
跨平台应用设置存储。
QStandardPaths
返回标准目录路径。
QDebug
调试输出工具。
QCalendar
支持多种日历系统。
QDeadlineTimer
截止时间管理。