启动 Qt5 控制台应用程序:invokemethod 与单次定时器

mal*_*ata 4 c++ qt qt5

我已经看到通过在事件循环开始时调用类方法来启动 Qt 控制台应用程序的两种不同方式。这种方式在事件循环开始后立即将要调用的方法排入队列,并且这种方式运行一个 singleShot 计时器,该计时器在事件循环开始后不久触发一个插槽执行。在这两种情况下,目标都是在执行类方法之前让事件循环运行。

这些对我来说似乎都不是特别干净,但我没有看到更好的。我对 Qt 也没有太多经验,所以我该说谁呢?

两种方式都有优势吗?invokeMethod 方式(第一个链接)似乎不像 singleShot timer 方式(第二个链接)那么常见,但除此之外,我没有理由遵循一种模式而不是另一种模式。

谢谢!

Ben*_*n T 5

QTimer::singleShot() 有一个带函数指针的重载(成员函数、函子或 lambda)。

使用此重载将提供编译时检查,这比使用函数名称时获得的运行时检查更好。此外,被调用的函数不需要是一个槽。

从 Qt 5.8 开始,没有这样的重载,QMetaObject::invokeMethod()因此您只能使用它们的名称来调用插槽。请注意,此功能将在 Qt 5.10 中添加。

恕我直言,编译时间检查足以使用QTimer::singleShot()(并搁置QMetaObject::invokeMethod()直到 5.10 出来)。

同样正如@Jeremy 指出的那样,QTimer::singleShot()以 0 毫秒的延迟调用最终会调用QMetaObject::invokeMethod(),但前提是您使用的是带插槽名称的重载(因此没有编译时检查)。QTimer::singleShot()使用函数指针的重载在0 ms 的情况下没有这样的优化,并且可能需要更多的 CPU 和内存来设置。

总结:

MyObject *object;

// 1: No compile time check for slot1, may fail at run time if slot1() does not exist
QMetaObject::invokeMethod(object, "slot1", Qt::QueuedConnection);

// 2: Calls 1 internally, but needs to do dome string editing to remove the decoration added by SLOT()
QTimer::singleShot(0, object, SLOT(slot1()));

// 3: Compile time check (i.e slot1() must exist), but creates a QSingleShotTimer internally (maybe less optimized)
QTimer::singleShot(0, object, &MyObject::slot1);
// QTimer::singleShot(0, [&](){printf("\o/"); object->slot1();}); // It can also call lambda 

// In any case, slot1 will be called as soon as event processing starts
app.exec()
Run Code Online (Sandbox Code Playgroud)