Как создать функцию паузы / ожидания с помощью Qt?
Я играю с Qt, и я хочу создать простую паузу между двумя командами. Однако это, кажется, не позволит мне использовать Sleep(int mili);, и я не могу найти никаких очевидных функций ожидания.
Я в основном просто делаю консольное приложение для тестирования некоторого кода класса, который позже будет включен в правильный графический интерфейс Qt, поэтому сейчас я не беспокоюсь о том, чтобы сломать всю управляемую событиями модель.
11 ответов:
этой предыдущий вопрос упоминает, используя
qSleep()который находится вQtTestмодуль. Чтобы избежать накладных расходов, связанных вQtTestмодуль, глядя на источник для этой функции, вы можете просто сделать свою собственную копию и вызвать ее. Он использует определяет для вызова окнаSleep()или Linuxnanosleep().#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 }
Я написал супер простую функцию задержки для приложения, которое я разработал в Qt.
Я бы посоветовал вам использовать этот код, а не функцию сна, поскольку он не позволит вашему графическому интерфейсу замерзнуть.
вот код:
void delay() { QTime dieTime= QTime::currentTime().addSecs(1); while (QTime::currentTime() < dieTime) QCoreApplication::processEvents(QEventLoop::AllEvents, 100); }чтобы задержать событие на n секунд-используйте
addSecs(n).
начиная с Qt5 мы также можем использовать
статические публичные члены QThread
void msleep(unsigned long msecs) void sleep(unsigned long secs) void usleep(unsigned long usecs)
маленький +1 к kshark27ответ, чтобы сделать его динамическим:
#include <QTime> void delay( int millisecondsToWait ) { QTime dieTime = QTime::currentTime().addMSecs( millisecondsToWait ); while( QTime::currentTime() < dieTime ) { QCoreApplication::processEvents( QEventLoop::AllEvents, 100 ); } }
мы использовали класс ниже -
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 предназначен для координации ожидания мьютекса между различными потоками. Но что делает эту работу является метод ожидания тайм-аут на него. При вызове таким образом, он функционирует точно так же, как функция сна, но он использует цикл событий Qt для синхронизации. Таким образом, никакие другие события или пользовательский интерфейс не блокируются, как обычная функция сна windows.
в качестве бонуса мы добавили функцию CancelSleep, чтобы разрешить другой часть программы для отмены функции "сна".
что нам понравилось в этом, так это то, что он легкий, многоразовый и полностью самодостаточный.
QMutex: http://doc.qt.io/archives/4.6/qmutex.html
QWaitCondition:http://doc.qt.io/archives/4.6/qwaitcondition.html
использовать стандартный сон функция добавить следующее в вашем .файл cpp:
#include <unistd.h>начиная с версии Qt 4.8, следующее сон функции:
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);
так как вы пытаетесь "проверить некоторый код класса", я бы действительно рекомендовал научиться использовать QTestLib. Он обеспечивает пространство имен это связано с тем и модуль 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()определенно было бы проще, если бы все, что вас интересует, это проверка нескольких вещей в команде линия.EDIT: на основе комментария, вот необходимые шаблоны использования.
во-первых, вам нужно отредактировать свой файл .pro, чтобы включить qtestlib:
CONFIG += qtestlibво-вторых, вы должны включить необходимые файлы:
- для это связано с пространством имен (в который входит
qSleep):#include <QTest>- для всех элементов
QtTestмодуль:#include <QtTest>. Это функционально эквивалентно добавлению Include для каждого элемента, который существует в пространстве имен.
У меня было много проблем на протяжении многих лет, пытаясь заставить 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(); }
похоже на некоторые ответы здесь, но, возможно, немного более легкий
void MyClass::sleepFor(qint64 milliseconds){ qint64 timeToExitFunction = QDateTime::currentMSecsSinceEpoch()+milliseconds; while(timeToExitFunction>QDateTime::currentMSecsSinceEpoch()){ QApplication::processEvents(QEventLoop::AllEvents, 100); } }
Если вы хотите использовать кросс-платформенный метод для этого, общий шаблон должен быть получен из QThread и создать функцию (статическую, если хотите) в производном классе, которая вызовет одну из функций сна в QThread.
@kshark27ответ не сработал для меня по какой-то причине (потому что я использую Qt 5.7?) так что я закончил тем, что сделал это:
while (someCondition) { // do something QApplication::processEvents(); QThread::sleep(1); // 1 second };Если это делается в потоке GUI, он, очевидно, вводит 1-секундную задержку GUI перед ответом на события пользователя. Но если вы можете жить с этим, это решение, вероятно, проще всего реализовать, и даже Qt одобряет его в своем Основы Резьбонарезной статьи (см. когда использовать альтернативы потокам).
Comments