Как мне создать функцию паузы / ожидания, используя Qt? - PullRequest
65 голосов
/ 20 сентября 2010

Я играю с Qt и хочу создать простую паузу между двумя командами. Однако, похоже, он не позволит мне использовать Sleep(int mili);, и я не могу найти очевидных функций ожидания.

Я просто создаю консольное приложение для тестирования некоторого кода класса, который позже будет включен в надлежащий графический интерфейс Qt, поэтому сейчас я не беспокоюсь о нарушении всей модели, управляемой событиями.

Ответы [ 12 ]

123 голосов
/ 15 июля 2012

Я написал супер простую функцию задержки для приложения, которое я разработал в Qt.

Я бы посоветовал вам использовать этот код, а не функцию сна, так как он не даст вашему графическому интерфейсу зависнуть.

Вот код:

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

Чтобы отложить событие на n секунд - используйте addSecs(n).

56 голосов
/ 19 марта 2015

Начиная с Qt5, мы также можем использовать

Статические открытые члены QThread

void    msleep(unsigned long msecs)
void    sleep(unsigned long secs)
void    usleep(unsigned long usecs)
31 голосов
/ 03 января 2014

Маленький +1 к kshark27 ответ, чтобы сделать его динамичным:

#include <QTime>

void delay( int millisecondsToWait )
{
    QTime dieTime = QTime::currentTime().addMSecs( millisecondsToWait );
    while( QTime::currentTime() < dieTime )
    {
        QCoreApplication::processEvents( QEventLoop::AllEvents, 100 );
    }
}
29 голосов
/ 20 сентября 2010

В этом предыдущем вопросе упоминается использование qSleep() в модуле QtTest.Чтобы избежать ненужных ссылок в модуле QtTest, глядя на источник этой функции, вы можете просто сделать свою собственную копию и вызвать ее.Он использует определения для вызова Windows Sleep() или 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
}
9 голосов
/ 21 сентября 2010

Мы использовали следующий класс -

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 разработан для координации мьютекса, ожидающего между различными потоками.Но что делает эту работу, так это то, что у метода wait есть тайм-аут.Когда вызывается таким образом, он функционирует точно так же, как функция сна, но он использует цикл событий Qt для синхронизации.Поэтому никакие другие события или пользовательский интерфейс не блокируются, как это делает обычная функция сна Windows.

В качестве бонуса мы добавили функцию CancelSleep, чтобы позволить другой части программы отменить функцию «сна».

Что нам понравилось в этом, так это то, что он легкий, многоразовый и полностью автономный.

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

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

6 голосов
/ 17 августа 2016

Чтобы использовать стандартную функцию sleep , добавьте в ваш файл .cpp следующее:

#include <unistd.h>

Начиная с версии 4.8 Qt, следующие функции sleep доступно:

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

Чтобы использовать их, просто добавьте в ваш файл .cpp следующее:

#include <QThread>

Ссылка: QThread (через документацию Qt): http://doc.qt.io/qt-4.8/qthread.html

В противном случае выполните эти шаги ...

Измените файл проекта следующим образом:

CONFIG += qtestlib

Обратите внимание, что в более новых версиях Qt вы получите следующую ошибку:

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

... итак, вместо этого измените файл проекта следующим образом:

QT += testlib

Затем в файле .cpp обязательно добавьте следующее:

#include <QtTest>

А затем используйте одну из функций сна следующим образом:

usleep(100);
6 голосов
/ 20 сентября 2010

Поскольку вы пытаетесь "протестировать некоторый код класса", я действительно рекомендую научиться использовать QTestLib . Он предоставляет пространство имен QTest и модуль QtTest , которые содержат ряд полезных функций и объектов, включая QSignalSpy , которые можно использовать для проверки того, что определенные сигналы излучаются .

Поскольку в конечном итоге вы будете интегрироваться с полным графическим интерфейсом, использование QTestLib и тестирование без ожидания или ожидания дадут вам более точный тест, который лучше отражает истинные шаблоны использования. Но если вы решите не идти по этому пути, вы можете использовать QTestLib :: qSleep , чтобы сделать то, что вы просили.

Поскольку вам просто нужна пауза между пуском насоса и его выключением, вы можете легко использовать таймер одиночного выстрела:

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();
}

Но qSleep() определенно будет проще, если все, что вас интересует, - это проверка нескольких вещей в командной строке.

РЕДАКТИРОВАТЬ : На основе комментария, вот необходимые шаблоны использования.

Во-первых, вам нужно отредактировать ваш .pro-файл, включив в него qtestlib:

CONFIG += qtestlib

Во-вторых, вам необходимо включить необходимые файлы:

  • Для пространства имен QTest (которое включает в себя qSleep): #include <QTest>
  • Для всех элементов в модуле QtTest: #include <QtTest>. Это функционально эквивалентно добавлению включения для каждого элемента, который существует в пространстве имен.
4 голосов
/ 24 марта 2017

В течение многих лет у меня было много проблем, когда я пытался заставить работать QApplication :: processEvents, как это используется в некоторых топовых ответах.IIRC, если несколько местоположений в итоге вызывают его, это может привести к тому, что некоторые сигналы не будут обработаны (https://doc.qt.io/archives/qq/qq27-responsive-guis.html). Мой обычный предпочтительный вариант - использовать 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();
}
2 голосов
/ 24 апреля 2014

Похоже на некоторые ответы здесь, но, возможно, немного более легкий

void MyClass::sleepFor(qint64 milliseconds){
    qint64 timeToExitFunction = QDateTime::currentMSecsSinceEpoch()+milliseconds;
    while(timeToExitFunction>QDateTime::currentMSecsSinceEpoch()){
        QApplication::processEvents(QEventLoop::AllEvents, 100);
    }
}
1 голос
/ 17 мая 2019

мы можем использовать следующий метод QT_Delay:

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

Это будет ждать 2 секунды перед вызовом print_lcd().

...