web-dev-qa-db-fra.com

Comment créer une fonction pause / attente à l'aide de 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.

En gros, je suis en train de créer une application console pour tester un code de classe qui sera plus tard inclus dans une interface graphique Qt appropriée. Par conséquent, pour le moment, je ne me soucie pas de casser tout le modèle piloté par les événements.

65
Zac

Cette question précédente mentionne l'utilisation de qSleep() qui se trouve dans le module QtTest. Pour éviter la surcharge de liaison dans le module QtTest, en regardant la source de cette fonction, vous pouvez simplement créer votre propre copie et l'appeler. Il utilise define 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
Arnold Spence

J'ai écrit une fonction de délai 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 de veille car il 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).

125
Kartik Sharma

À partir de Qt5, nous pouvons également utiliser

Membres publics statiques de QThread

void    msleep(unsigned long msecs)
void    sleep(unsigned long secs)
void    usleep(unsigned long usecs)
59
Yash

La petite réponse de +1 à kshark27 pour le rendre dynamique:

#include <QTime>

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

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 mutex entre différents threads. Mais ce qui fait que cela fonctionne, c'est que la méthode d'attente a un délai d'attente. Appelé de cette façon, il fonctionne exactement comme une fonction de veille, mais il utilise la boucle d'événement de Qt pour le minutage. Ainsi, aucun autre événement ni l'interface utilisateur n'est bloqué, contrairement à la fonction de veille Windows normale.

En prime, nous avons ajouté la fonction CancelSleep pour permettre à une autre partie du programme d’annuler la fonction "veille".

Ce que nous avons aimé à propos de cela, c’est qu’il 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

9
photo_tom

Pour utiliser la fonction standard sleep , ajoutez ce qui suit dans votre fichier .cpp:

#include <unistd.h>

A partir de 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, ajoutez simplement les éléments suivants dans votre fichier .cpp:

#include <QThread>

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

Sinon, suivez ces étapes ...

Modifiez le fichier 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.

... donc, modifiez plutôt le fichier de projet comme suit:

QT += testlib

Ensuite, dans votre fichier .cpp, veillez à ajouter les éléments suivants:

#include <QtTest>

Et utilisez ensuite l’une des fonctions de sommeil comme ceci:

usleep(100);
6
Richard Nalezynski

Puisque vous essayez de "tester du code de classe", je recommanderais vraiment d'apprendre à utiliser QTestLib . Il fournit un espace de noms QTest et un module QtTest contenant un certain nombre de fonctions et d'objets utiles, notamment QSignalSpy que vous pouvez utiliser pour vérifier que des signaux sont émis.

Etant donné que vous intégrerez éventuellement une interface graphique complète, l'utilisation de QTestLib et le test sans sommeil ni attente vous donneront un test plus précis - un test qui représente mieux les véritables modèles d'utilisation. Mais, si vous choisissez de ne pas suivre cette voie, vous pouvez utiliser QTestLib :: qSleep pour faire ce que vous avez demandé.

Puisque vous avez juste besoin d’une pause entre le démarrage de votre pompe et son arrêt, vous pouvez facilement utiliser un minuteur simple coup:

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éressait était de vérifier quelques éléments de la ligne de commande.

[~ # ~] edit [~ # ~] : En fonction du commentaire, voici les modèles d'utilisation requis.

Tout d’abord, vous devez éditer 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 <QTest>
  • Pour tous les éléments du module QtTest: #include <QtTest>. Cela revient fonctionnellement à ajouter une inclusion pour chaque élément existant dans l'espace de noms.
6
Kaleb Pederson

Au fil des ans, j'ai eu beaucoup de difficulté à essayer de faire fonctionner QApplication :: processEvents, comme cela est utilisé dans certaines des principales réponses. IIRC, si plusieurs sites finissent par l'appeler, des signaux peuvent 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();
}
4
dvntehn00bz

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
hytromo

nous pouvons utiliser la méthode suivante QT_Delay:

QTimer::singleShot(2000,this,SLOT(print_lcd()));

Cela va attendre 2 secondes avant d'appeler print_lcd().

1
user11514364

La réponse de @ kshark27 n'a pas fonctionné pour moi pour une raison quelconque (parce que j'utilise Qt 5.7?) alors j'ai fini par faire ceci:

while (someCondition) {

   // do something

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

};

Si cela est fait dans le fil de l'interface graphique, cela introduit évidemment un décalage de 1 seconde avant de répondre aux événements de l'utilisateur. Mais si vous pouvez vivre avec, cette solution est probablement la plus facile à implémenter et même Qt l’approuve dans leur article Threading Basics (voir Quand utiliser des alternatives aux threads section).

1
TranslucentCloud

Si vous voulez une méthode multiplate-forme pour ce faire, le modèle général consiste à dériver de QThread et à créer une fonction (statique, si vous le souhaitez) dans votre classe dérivée qui appellera l’une des fonctions de veille de QThread.

1
San Jacinto