Qt で遊んでいるので、2つのコマンドの間に単純な一時停止を作成したい。しかし、Sleep(int mili);
を使用できるようには思われないため、明らかな待機関数は見つかりません。
基本的に、後で適切なQt GUIに含まれるクラスコードをテストするためのコンソールアプリケーションを作成しているだけなので、今のところ、イベント駆動型モデル全体を壊すことを気にしません。
この 前の質問 は、QtTest
モジュールにあるqSleep()
を使用することに言及しています。 QtTest
モジュールでのオーバーヘッドリンクを回避するには、その関数のソースを見て、独自のコピーを作成して呼び出します。 defineを使用して、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
}
Qtで開発したアプリケーション用に、非常に単純な遅延関数を作成しました。
GUIがフリーズしないため、スリープ関数ではなくこのコードを使用することをお勧めします。
コードは次のとおりです。
void delay()
{
QTime dieTime= QTime::currentTime().addSecs(1);
while (QTime::currentTime() < dieTime)
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}
イベントをn秒遅延させるには、addSecs(n)
を使用します。
Qt5以降では、
void msleep(unsigned long msecs)
void sleep(unsigned long secs)
void usleep(unsigned long usecs)
動的にするための kshark27 の回答への+1:
#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は、異なるスレッド間でミューテックス待機を調整するように設計されています。しかし、これが機能するのは、waitメソッドにタイムアウトが設定されているためです。この方法で呼び出されると、スリープ機能とまったく同じように機能しますが、タイミングにQtのイベントループを使用します。したがって、他のイベントやUIは、通常のWindowsスリープ機能のようにブロックされません。
ボーナスとして、CancelSleep関数を追加して、プログラムの別の部分で「スリープ」機能をキャンセルできるようにしました。
この点で気に入ったのは、軽量で再利用可能で、完全に自己完結型であるということです。
QMutex: http://doc.qt.io/archives/4.6/qmutex.html
QWaitCondition: http://doc.qt.io/archives/4.6/qwaitcondition.html
標準sleep関数を使用するには、次を.cppファイルに追加します。
#include <unistd.h>
Qtバージョン4.8では、次の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);
「いくつかのクラスコードをテスト」しようとしているので、 QTestLib の使用を学ぶことをお勧めします。 QTestネームスペース と QtTestモジュール を提供します。これには、 QSignalSpy 信号が発信されます。
最終的には完全なGUIと統合されるので、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>
。これは、名前空間内に存在する各アイテムにインクルードを追加することと機能的に同等です。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);
}
}
次のメソッドQT_Delay
を使用できます。
QTimer::singleShot(2000,this,SLOT(print_lcd()));
これは、print_lcd()
を呼び出す前に2秒間待機します。
@ kshark27 の答えは、何らかの理由で(Qt 5.7を使用しているので?)私にはうまくいきませんでした。
while (someCondition) {
// do something
QApplication::processEvents();
QThread::sleep(1); // 1 second
};
これがGUIスレッドで行われる場合、ユーザーイベントに応答する前に1秒のGUIラグが明らかに導入されます。しかし、あなたがそれと一緒に生きることができるなら、このソリューションはおそらく実装が最も簡単であり、Qtでさえ Threading Basics の記事で推奨しています(を参照してくださいセクション)。
クロスプラットフォームでこれを行う方法が必要な場合、一般的なパターンはQThreadから派生し、派生クラスでQThreadのスリープ関数の1つを呼び出す関数(必要に応じて静的)を作成します。