93 votes

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

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

Je suis essentiellement en train de créer une application console pour tester du code de classe qui sera ensuite inclus dans une véritable interface graphique Qt, donc pour le moment je ne me soucie pas de rompre tout le modèle événementiel.

0 votes

Que testez-vous exactement? Que fait-on en ajoutant une fonction wait() ou sleep()?

1 votes

Je crée une classe pour piloter une pompe péristaltique en utilisant des commandes sérielles RS232. J'ai créé une interface graphique en QT mais en attendant, je teste simplement les fonctions que j'ai créées à partir d'une fonction main() dans la console. Ainsi, je veux que la classe soit compilée par QT mais en même temps je veux que mypump.startpump(); sleep(1000); mypump.stoppump(); par exemple, juste pour tester que cela fonctionne.

0 votes

Malgré la compilation avec QT, j'utilise CONFIG += console pour exécuter et afficher les chaînes de débogage dans la console.

156voto

kshark27 Points 539

J'ai écrit une fonction de retard super simple pour une application que j'ai développée en Qt.

Je vous conseillerais d'utiliser ce code plutôt que la fonction sleep car cela ne laissera pas votre interface graphique se figer.

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).

2 votes

Merci beaucoup pour cette belle fonction ! Exactement ce que je cherchais car elle ne suspend pas la boucle d'événements principale.

0 votes

C'est l'un de ces petits morceaux de code que vous trouvez de temps en temps et auquel vous pensez simplement "Pourquoi n'y ai-je pas pensé". Bon travail.

8 votes

Suis-je le seul à rencontrer une charge CPU de 100 % en mettant cela dans une boucle while dans Qt 5.7 ?

38voto

Arnold Spence Points 12759

Cette question précédente mentionne l'utilisation de qSleep() qui se trouve dans le module QtTest. Pour éviter le surcoût de liaison dans le module QtTest, en regardant le code source de cette fonction, vous pourriez simplement en faire une copie et l'appeler. Il utilise des définitions pour appeler soit Sleep() sous Windows soit nanosleep() sous Linux.

#ifdef Q_OS_WIN
#include  // pour 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
}

0 votes

Merci, l'inclusion de windows.h permet l'utilisation de Sleep(); Cela suffira pour le moment car je comprends que je n'utiliserai pas ce code dans le programme final car il casse le modèle basé sur les événements, mais pour le moment cela me permet de tester le programme tel quel.

0 votes

Où avez-vous trouvé la source ?

0 votes

Cela fait maintenant six ans et quelques changements ont eu lieu, mais vous pouvez trouver la version open source de Qt sur qt.io/download-open-source. Il y a des liens là-bas qui mèneront au code source. Je ne sais pas si le code ci-dessus existe toujours.

37voto

GraehamF Points 670

Petit +1 à la réponse de kshark27 pour la rendre dynamique :

#include <QTime>

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

0 votes

Plus un, petite note : je suppose que tu #include également `#include `

4 votes

Voir les commentaires ci-dessus. Cela peut entraîner une occupation à 100 % du processeur en attente dans des circonstances normales (file d'événements vide) et des problèmes plus graves si l'horloge du système est ajustée lorsque la boucle est en cours d'exécution.

0 votes

include

9voto

photo_tom Points 4160

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 l'attente du mutex entre différents threads. Mais ce qui rend cela possible, c'est que la méthode d'attente a un délai d'expiration. Lorsqu'elle est appelée de cette manière, elle fonctionne exactement comme une fonction sleep, mais elle utilise la boucle d'événements de Qt pour le timing. Ainsi, aucun autre événement ou l'interface utilisateur ne sont bloqués comme le fait normalement la fonction de veille de Windows.

En bonus, nous avons ajouté la fonction CancelSleep pour permettre à une autre partie du programme d'annuler la fonction "sleep".

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

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

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

0 votes

Au moins l'implémentation actuelle dans qt5 ne semble pas du tout communiquer avec la boucle d'événements, donc du point de vue du "traitement des événements" il s'agit d'un "sommeil interruptible".

6voto

Kaleb Pederson Points 22428

Étant donné que vous essayez de "tester un certain code de classe", je vous recommande vraiment d'apprendre à utiliser QTestLib. Il fournit un espace de noms QTest et un module QtTest 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.

Comme vous finirez par vous intégrer à une GUI complète, utiliser QTestLib et tester sans dormir ou attendre vous donnera un test plus précis - un test qui représente mieux les véritables modèles d'utilisation. Cependant, si vous choisissez de ne pas suivre cette voie, vous pourriez 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 son arrêt, vous pourriez facilement utiliser un minuteur à coup unique :

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.

MODIFICATION : En fonction du commentaire, voici les modèles d'utilisation requis.

Tout d'abord, vous devez modifier votre fichier .pro pour inclure qtestlib :

CONFIG += qtestlib

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

  • Pour l'espace de noms QTest (qui inclut qSleep) : #include
  • Pour tous les éléments du module QtTest : #include . Cela équivaut fonctionnellement à ajouter une inclusion pour chaque élément qui existe dans l'espace de noms.

0 votes

Comment inclure QTestlib? Le #include semble ne pas pouvoir le trouver.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X