qtimer qt

import qtimer



QTimer:: singleShot y QMetaMethod:: invoke (3)

Cada sistema tiene un bucle de eventos donde se procesan los eventos. Di como

application::processEvents() { // process event list.. }

Ahora el lugar donde escribes QTimer::singleShot(0, this, SLOT(doSomething())); podría estar dentro de algún evento de procesamiento. Cuando se completa este ciclo, se llamará de nuevo a processEvents y se ejecutará doSomething ().

Así que esto es como llamar a doSomething en el próximo ciclo de eventos, en lugar de llamarlo inmediatamente. Espero que entiendas la idea.

En algunos ejemplos de Qt, veo que usan QTimer::singleShot(0, this , SLOT(funcA())) , ¿por qué no llamar directamente a la ranura funcA ? también la misma pregunta para usar QMetaMethod::invoke para llamar a la función con parámetros.


Estos métodos también se pueden usar para invocar miembros protegidos y privados de una clase (si están definidos como espacios) de un ámbito que de otro modo requeriría acceso público.


Las siguientes líneas son todas funcionalmente equivalentes:

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

Como ahora es evidente, la intención es ejecutar la llamada dentro del bucle de evento. La llamada en cola da como resultado la publicación de un QMetaCallEvent en el object . Este evento es manejado por QObject::event y da como resultado la llamada del método deseado. Por lo tanto, los siguientes son exactamente equivalentes, incluso si este último es un detalle de implementación privada, lo que me permite omitir los detalles de creación de instancias del evento :

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

Esto es útil en diversas situaciones. Por ejemplo:

  • Para ejecutar algún código después de que se hayan manejado todos los eventos publicados hasta ahora.

  • Para ejecutar solo después de que el ciclo de evento haya comenzado.

  • Llamar a un método invokable que no es accesible debido a los modificadores de acceso de C ++. Los métodos invocables son: señales, intervalos y métodos declarados Q_INVOKABLE .

  • La llamada directa no es segura (léase: ¡error!) Cuando un QObject reside en otro hilo, a menos que llame explícitamente a un método documentado como seguro para subprocesos.

La llamada en cola es una necesidad si desea asegurarse de que un bucle de evento finalice inmediatamente: una llamada directa a la quit() es una operación no operativa si el ciclo no se está ejecutando todavía.

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 }

Lo ideal sería utilizar postToThread partir de esta respuesta , que ofrece la forma más económica de llamar a los métodos en otros hilos:

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

Una forma alternativa de hacerlo es usar un QObject como fuente de señal:

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 }

Otra forma sería usar un evento personalizado y actuar en su destructor:

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 }