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

这些对我来说似乎都不是特别干净,但是我没有看到更好的东西。我在Qt方面也没有太多经验,那么我要说的是谁?

两种方式都有优势吗? invokeMethod方式(第一个链接)似乎不像singleShot计时器方式(第二个链接)那样普遍,但是除此之外,我没有理由遵循一种模式。

谢谢!

最佳答案

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

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

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

恕我直言,编译时间检查足以使用QTimer::singleShot()(并保留QMetaObject::invokeMethod()直到5.10到期)。

同样正如@Jeremy所指出的,延迟0毫秒调用QTimer::singleShot()最终会调用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()

关于c++ - 启动Qt5控制​​台应用程序:invokemethod与singleshot计时器,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43671504/

10-11 17:05