我已经看到了两种不同的方法,可以在事件循环开始时通过调用类方法来启动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/