Comment créer une fonction pause / attente en utilisant Qt?

je joue avec Qt , et je veux créer une simple pause entre deux commandes. Cependant, il ne semble pas me laisser utiliser Sleep(int mili); , et je ne trouve aucune fonction d'attente évidente.

je suis essentiellement juste en train de faire une application de console pour tester un code de classe qui sera plus tard inclus dans une interface graphique Qt appropriée, donc pour l'instant je ne me soucie pas de briser le modèle tout entier event-driven.

58
demandé sur Peter Mortensen 2010-09-20 19:07:06

11 réponses

cette question précédente mentionne l'utilisation de qSleep() qui est dans le module QtTest . Pour éviter le lien dans le module QtTest , en regardant la source de cette fonction, vous pouvez simplement faire votre propre copie et l'appeler. Il utilise des définitions pour appeler Windows Sleep() ou Linux nanosleep() .

#ifdef Q_OS_WIN
#include <windows.h> // for Sleep
#endif
void QTest::qSleep(int ms)
{
    QTEST_ASSERT(ms > 0);

#ifdef Q_OS_WIN
    Sleep(uint(ms));
#else
    struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
    nanosleep(&ts, NULL);
#endif
}
29
répondu Arnold Spence 2017-05-23 12:26:27

j'ai écrit une fonction de retard très simple pour une application que j'ai développée dans Qt.

je vous conseille d'utiliser ce code plutôt que la fonction sommeil car il ne laissera pas votre interface graphique geler.

voici le code:

void delay()
{
    QTime dieTime= QTime::currentTime().addSecs(1);
    while (QTime::currentTime() < dieTime)
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

pour retarder un événement de n secondes - utilisez addSecs(n) .

118
répondu kshark27 2015-07-14 16:21:40

à partir de Qt5, nous pouvons également utiliser

Statique le Public et les Membres de QThread

void    msleep(unsigned long msecs)
void    sleep(unsigned long secs)
void    usleep(unsigned long usecs)
43
répondu Yash 2018-05-18 21:24:11

petit +1 à kshark27 'S réponse to make it dynamic:

#include <QTime>

void delay( int millisecondsToWait )
{
    QTime dieTime = QTime::currentTime().addMSecs( millisecondsToWait );
    while( QTime::currentTime() < dieTime )
    {
        QCoreApplication::processEvents( QEventLoop::AllEvents, 100 );
    }
}
30
répondu GraehamF 2017-05-23 12:34:41

nous avons utilisé la classe ci-dessous -

class SleepSimulator{
     QMutex localMutex;
     QWaitCondition sleepSimulator;
public:
    SleepSimulator::SleepSimulator()
    {
        localMutex.lock();
    }
    void sleep(unsigned long sleepMS)
    {
        sleepSimulator.wait(&localMutex, sleepMS);
    }
    void CancelSleep()
    {
        sleepSimulator.wakeAll();
    }
};

QWaitCondition est conçu pour coordonner mutex attente entre différents threads. Mais ce qui fait ce travail est la méthode d'attente a un temps d'arrêt sur elle. Lorsqu'il est appelé de cette façon, il fonctionne exactement comme une fonction de sommeil, mais il utilise la boucle d'événement de Qt pour le timing. Ainsi, aucun autre événement ou L'UI sont bloqués comme la fonction normale de sommeil de fenêtres fait.

en bonus, nous avons ajouté le CancelSleep fonction permettant à une autre partie du programme d'annuler la fonction "sommeil".

Ce que nous avons aimé, c'est que c'léger, réutilisable et est complètement autonome.

QMutex: http://doc.qt.io/archives/4.6/qmutex.html

QWaitCondition: http://doc.qt.io/archives/4.6/qwaitcondition.html

8
répondu photo_tom 2015-11-24 07:50:08

pour utiliser la fonction sleep ajouter ce qui suit dans votre .fichier cpp:

#include <unistd.h>

depuis la version 4.8 De Qt, les fonctions suivantes sleep sont disponibles:

void QThread::msleep(unsigned long msecs)
void QThread::sleep(unsigned long secs)
void QThread::usleep(unsigned long usecs)

pour les utiliser, il suffit d'ajouter ce qui suit dans votre .fichier cpp:

#include <QThread>

référence: QThread (via la documentation Qt)): http://doc.qt.io/qt-4.8/qthread.html

sinon, effectuer ces étapes...

modifier le dossier de projet comme suit:

CONFIG += qtestlib

notez que dans les versions plus récentes de Qt vous obtiendrez l'erreur suivante:

Project WARNING: CONFIG+=qtestlib is deprecated. Use QT+=testlib instead.

... ainsi, à la place, modifiez le dossier de projet comme suit:

QT += testlib

alors, dans votre .fichier cpp, assurez-vous d'ajouter ce qui suit:

#include <QtTest>

et puis utilisez l'une des fonctions du sommeil comme suit:

usleep(100);
6
répondu Richard Nalezynski 2016-08-16 21:00:34

puisque vous essayez de "tester un code de classe", je recommande vraiment d'apprendre à utiliser QTestLib . Il fournit un qtest espace de nom et un qtttest module qui contiennent un certain nombre de fonctions et d'objets utiles, y compris QSignalSpy que vous pouvez utiliser pour vérifier que certains signaux sont émis.

puisque vous finirez par vous intégrer avec une interface graphique complète, en utilisant QTestLib et testing sans sommeil ni attente vous donneront un test plus précis -- un test qui représente mieux les vrais modèles d'utilisation. Mais, si vous choisissez de ne pas prendre cette route, vous pouvez utiliser QTestLib::qSleep pour faire ce que vous avez demandé.

comme vous avez juste besoin d'une pause entre le démarrage de votre pompe et sa fermeture, vous pouvez facilement utiliser un minuteur de tir simple:

class PumpTest: public QObject {
    Q_OBJECT
    Pump &pump;
public:
    PumpTest(Pump &pump):pump(pump) {};
public slots:
    void start() { pump.startpump(); }
    void stop() { pump.stoppump(); }
    void stopAndShutdown() {
        stop();
        QCoreApplication::exit(0);
    }
    void test() {
        start();
        QTimer::singleShot(1000, this, SLOT(stopAndShutdown));
    }
};

int main(int argc, char* argv[]) {
    QCoreApplication app(argc, argv);
    Pump p;
    PumpTest t(p);
    t.test();
    return app.exec();
}

Mais qSleep() serait certainement plus facile si tout ce qui vous intéresse est de vérifier quelques choses sur la ligne de commande.

EDIT : basé sur le commentaire, voici les modèles d'utilisation requis.

tout d'Abord, vous devez modifier votre .pro fichier à inclure qtestlib:

CONFIG += qtestlib

Deuxièmement, vous devez inclure les fichiers nécessaires:

  • pour L'espace de noms QTest (qui comprend qSleep ): #include <QTest>
  • pour tous les éléments du module QtTest : #include <QtTest> . Cela équivaut fonctionnellement à ajouter une inclusion pour chaque élément qui existe dans l'espace de noms.
5
répondu Kaleb Pederson 2015-11-24 07:37:43

j'ai eu beaucoup de problèmes au cours des années à essayer d'obtenir QApplication::processEvents de travail, comme c'est utilisé dans certains des top-réponses. IIRC, si plusieurs emplacements finissent par l'appeler, il peut finir par causer certains signaux de ne pas être traités ( https://doc.qt.io/archives/qq/qq27-responsive-guis.html ). Mon option préférée habituelle est d'utiliser un QEventLoop ( https://doc.qt.io/archives/qq/qq27-responsive-guis.html#waitinginalocaleventloop ).

inline void delay(int millisecondsWait)
{
    QEventLoop loop;
    QTimer t;
    t.connect(&t, &QTimer::timeout, &loop, &QEventLoop::quit);
    t.start(millisecondsWait);
    loop.exec();
}
3
répondu dvntehn00bz 2017-03-24 15:18:40

semblable à certaines réponses ici, mais peut-être un peu plus léger

void MyClass::sleepFor(qint64 milliseconds){
    qint64 timeToExitFunction = QDateTime::currentMSecsSinceEpoch()+milliseconds;
    while(timeToExitFunction>QDateTime::currentMSecsSinceEpoch()){
        QApplication::processEvents(QEventLoop::AllEvents, 100);
    }
}
2
répondu hytromo 2014-04-23 22:25:50

si vous voulez une méthode multiplateformes pour faire cela, le modèle général est de dériver de QThread et de créer une fonction (statique, si vous voulez) dans votre classe dérivée qui appellera l'une des fonctions de sommeil dans QThread.

1
répondu San Jacinto 2010-09-20 23:55:14

@kshark27 ' S réponse n'a pas fonctionné pour moi pour une raison quelconque (parce que j'utilise Qt 5.7?

while (someCondition) {

   // do something

   QApplication::processEvents();
   QThread::sleep(1); // 1 second

};

si cela est fait dans le thread GUI, cela introduit évidemment un décalage de 1 seconde avant de répondre aux événements utilisateur. Mais si vous pouvez vivre avec, cette solution est probablement une plus facile à mettre en œuvre et même Qt l'approuve dans leur Threading Basics article (voir quand utiliser Alternatives aux Threads section).

1
répondu TranslucentCloud 2018-01-17 09:43:55