gpt4 book ai didi

QTimer::singleShot 和 QMetaMethod::invoke

转载 作者:行者123 更新时间:2023-12-01 17:27:11 26 4
gpt4 key购买 nike

在一些 Qt 示例中,我看到他们使用QTimer::singleShot(0, this , SLOT(funcA())),为什么不直接调用槽funcA?使用 QMetaMethod::invoke 调用带参数的函数也是同样的问题。

最佳答案

以下几行在功能上都是等效的:

QTimer::singleShot(0, object, &Class::funcA); // Qt 5
QTimer::singleShot(0, object, SLOT(funcA())); // Qt 4
QMetaObject::invokeMethod(object, "funcA", Qt::QueuedConnection);

现在很明显,其目的是在事件循环内执行调用。排队的调用会导致将 QMetaCallEvent 发布到对象。该事件由QObject::event 处理并导致调用所需的方法。因此,以下内容完全等效,即使后者是私有(private)实现细节 - 让我跳过 the details of instantiating the event :

QMetaObject::invokeMethod(object, "funcA", Qt::QueuedConnection);
QCoreApplication::postEvent(object, new QMetaCallEvent{...});

这在各种情况下都很方便。例如:

  • 在处理所有迄今为止发布的事件后执行一些代码。

  • 仅在事件循环启动后执行。

  • 调用由于 C++ 访问修饰符而无法访问的可调用方法。可调用的方法有:信号、槽和声明为Q_INVOKABLE的方法。

  • QObject驻留在另一个线程中时,直接调用是不安全的(读取:错误!),除非您显式调用记录为线程安全的方法。

如果您希望确保事件循环立即退出,则排队调用是必要的:如果循环尚未运行,则直接 quit() 调用是无操作。

int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
app.quit(); // this is a no-op since the event loop isn't running yet
return app.exec(); // will not quit as desired
}

int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
QMetaObject::invokeMethod(&app, "quit", Qt::QueuedConnection);
return app.exec(); // will return immediately
}

理想情况下,您可以使用 this answer 中的 postToThread ,它提供了在其他线程中调用方法的最低成本的方式:

int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
postToThread([]{ qApp->quit(); });
}

另一种方法是使用 QObject 作为信号源:

int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
{
QObject src;
src.connect(&src, &QObject::destroyed, &app, &QCoreApplication::quit,
Qt::QueuedConnection);
}
return app.exec(); // will return immediately
}

另一种方法是使用自定义事件并在其析构函数中执行操作:

int main(int argc, char ** argv) {
QCoreApplication app{argc, argv};
struct QuitEvent : QEvent {
QuitEvent() : QEvent(QEvent::None) {}
~QuitEvent() { qApp->quit(); }
};
QCoreApplication::postEvent(&app, new QuitEvent);
return app.exec(); // will return immediately
}

关于QTimer::singleShot 和 QMetaMethod::invoke,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24142450/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com