MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
Qtの基礎 - タイマのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
Qtの基礎 - タイマ
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == <code>QTimer</code>クラスは、時間ベースのイベントを処理するためのクラスである。<br> 主に、一定の間隔で特定の処理を実行する場合に使用する。<br> <br> <code>QTimer</code>クラスは、まず、<code>QTimer</code>オブジェクトを作成して、<code>start</code>メソッドを呼び出して起動する。<br> タイマ時間が過ぎると、<code>timeout</code>シグナルが発行される。<br> このシグナルを任意のスロットに接続することにより、定期的に処理を実行することができる。<br> <br> タイマの精度は、OSやハードウェアに依存する。<br> ミリ秒単位での制御が可能であるが、極端に短い間隔を設定する場合、システムの負荷が高くなる可能性があるため注意が必要である。<br> <br> <code>QTimer</code>クラスには、単発のタイマと繰り返しのタイマが存在する。<br> 単発のタイマは<code>singleShot</code>メソッド (staticメソッド) を使用してに設定することができる。<br> 一方、繰り返しのタイマは、QTimerオブジェクトを使用して実装する。<br> <br> <code>QTimer</code>クラスのメリットとして、Qtのイベントループと統合されているため、他のQtのコンポーネントとシームレスに連携できることが挙げられる。<br> また、マルチスレッド環境でも安全に使用できるよう設計されている。<br> <br> タイマの制御には、<code>start</code>メソッドの他に<code>stop</code>メソッドがあり、これを使用してタイマを一時停止することができる。<br> また、<code>isActive</code>メソッドを使用して、タイマが現在アクティブかどうかを確認することもできる。<br> <br> <code>QTimer</code>クラスは、UIの更新、ネットワーク操作のタイムアウト、アニメーションの制御等、様々な用途に活用できる便利なクラスである。<br> ただし、過度に多くのタイマを同時に使用する場合は、アプリケーションのパフォーマンスに影響を与える可能性があるため、適切な設計と使用が求められる。<br> <br><br> == 単発のタイマ == ==== コンソールアプリケーション ==== 以下の例では、単発タイマを使用して、指定時間後に1度だけメッセージを表示している。<br> <syntaxhighlight lang="c++"> // TimerExample.hファイル #include <QCoreApplication> #include <QTimer> #include <stdexcept> #include <QDebug> class TimerExample : public QObject { Q_OBJECT public: TimerExample(QObject *parent = nullptr) : QObject(parent) {} void startTimer(int milliseconds) { // startTimer(0)のように呼び出す場合は例外エラーとする try { if (milliseconds <= 0) { throw std::invalid_argument("Timer duration must be positive"); } QTimer::singleShot(milliseconds, this, &TimerExample::onTimeout); qDebug() << "Timer started for" << milliseconds << "milliseconds"; } catch (const std::exception& e) { qCritical() << "エラー: " << e.what(); } } private slots: void onTimeout() { qDebug() << "Timer expired!"; emit finished(); } signals: void finished(); }; </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // main.cppファイル #include "TimerExample.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); TimerExample example; QObject::connect(&example, &TimerExample::finished, &a, &QCoreApplication::quit); example.startTimer(5000); // 5秒後にタイマイベント開始 return a.exec(); } </syntaxhighlight> <br> ==== QWidgetアプリケーション ==== 以下の例では、QTimerクラスの単発タイマ機能を使用して、UIを定期的に更新している。<br> <br> 具体的なタイマの動作を以下に示す。<br> * startCountdownスロットにて、10秒のカウントダウンを開始する。 * updateTimerスロットにて、1秒ごとにカウントダウンを更新して、UIを更新する。 * QTimer::singleShotメソッドを再帰的に使用して、1秒ごとの更新を実現する。 <br> <syntaxhighlight lang="c++"> // CountdownWindow.hファイル #include <QApplication> #include <QMainWindow> #include <QVBoxLayout> #include <QLabel> #include <QPushButton> #include <QTimer> class CountdownWindow : public QMainWindow { Q_OBJECT private: int m_secondsLeft; QLabel *m_timeLabel; QPushButton *m_startButton; public: CountdownWindow(QWidget *parent = nullptr) : QMainWindow(parent), m_secondsLeft(10) { setWindowTitle("Countdown Timer"); QWidget *centralWidget = new QWidget(this); setCentralWidget(centralWidget); QVBoxLayout *layout = new QVBoxLayout(centralWidget); m_timeLabel = new QLabel("Time left: 10 seconds", this); layout->addWidget(m_timeLabel); m_startButton = new QPushButton("Start Countdown", this); layout->addWidget(m_startButton); connect(m_startButton, &QPushButton::clicked, this, &CountdownWindow::startCountdown); } private slots: void startCountdown() { m_secondsLeft = 10; updateDisplay(); m_startButton->setEnabled(false); // 1秒ごとにupdateTimerを呼び出す QTimer::singleShot(1000, this, &CountdownWindow::updateTimer); } void updateTimer() { m_secondsLeft--; updateDisplay(); if (m_secondsLeft > 0) { // カウントダウンが終わっていない場合、再度タイマをセット QTimer::singleShot(1000, this, &CountdownWindow::updateTimer); } else { m_startButton->setEnabled(true); } } void updateDisplay() { m_timeLabel->setText(QString("Time left: %1 seconds").arg(m_secondsLeft)); } }; </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // main.cppファイル #include "CountdownWindow.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); CountdownWindow window; window.resize(300, 150); window.show(); return app.exec(); } </syntaxhighlight> <br><br> == 繰り返しタイマ == 以下の例では、ダイアログを開いて画像を表示している。<br> 1秒ごとに画像の大きさを変化させる。<br> <br> ダイアログを閉じる時、タイマを解除する。<br> <syntaxhighlight lang="c++"> // MainWindow.h private: int m_TimerID; int m_AdjustGraphicSize; std::unique_ptr<QLabel> m_pLabel; private: void GraphicTimer(); protected: void timerEvent(QTimerEvent *pEvent); private slots: void CloseDialog(); </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // MainWindow.cpp // モーダルダイアログに画像を貼り付けて、1秒のタイマを設定して表示する void MainWindow::GraphicTimer() { m_AdjustGraphicSize = 1; m_pLabel = std:make_unique<QLabel>; m_pLabel->setFixedSize(32, 32); m_pLabel->setScaledContents(true); QPixmap pixmap = QApplication::style()->standardPixmap(QStyle::SP_FileDialogContentsView); m_pLabel->setPixmap(pixmap); std::unique_ptr<QHBoxLayout> pHbox1 = std::make_unique<QHBoxLayout>; pHbox1->addWidget(m_pLabel); pHbox1->addStretch(); std::unique_ptr<QPushButton> pBtn = std::make_unique<QPushButton>(tr("閉じる")); pBtn->setFixedSize(80, 28); // プッシュボタンのシグナルとCloseDialogスロットを接続する connect(pBtn, SIGNAL(clicked()), this, SLOT(CloseDialog())); std::unique_ptr<QHBoxLayout> pHbox2 = std::make_unique<QHBoxLayout>; pHbox2->addStretch(); pHbox2->addWidget(pBtn); pHbox2->addStretch(); std::unique_ptr<QVBoxLayout> pVbox = std::make_unique<QVBoxLayout>; pVbox->addLayout(pHbox1); pVbox->addStretch(); pVbox->addLayout(pHbox2); std::unique_ptr<QDialog> Dlg = std::make_unique<QDialog>(this, 0); Dlg->setModal(true); Dlg->setSizeGripEnabled(false); Dlg->setWindowTitle(tr("タイマテスト")); Dlg->setMinimumSize(240, 280); Dlg->setMaximumSize(240, 280); Dlg->setLayout(pVbox); m_TimerID = startTimer(1000); Dlg->exec(); killTimer(m_TimerID); } // イベント処理 // ラベルサイズを32[px]〜200[px]の範囲で16[px]ずつ増減する // m_AdjustGraphicSizeの値により大小を決める // 全てのタイマイベントは当メソッドに来るため、タイマIDで処理を振り分ける // 変数m_AdjustGraphicSizeには、1または-1が代入される void MainWindow::timerEvent(QTimerEvent *pEvent) { if(pEvent->timerId() == m_TimerID) { int sz = m_pLabel->width() + m_AdjustGraphicSize * 16; m_pLabel->setFixedSize(sz, sz); if(sz > 200 || sz <= 32) { m_AdjustGraphicSize *= -1; } } } // ダイアログの終了処理 // 送信元のウインドウがダイアログの場合、doneで終了する(doneの引数は、execの戻り値である) void MainWindow::CloseDialog() { QWidget *pWindow = static_cast<QWidget *>(sender())->window(); if(pWindow->inherits("QDialog")) { QDialog *Dlg = static_cast<QDialog *>(pWindow); Dlg->done(0); } } </syntaxhighlight> <br><br> == QTimerを即タイムアウトする == <code>QTimer</code>クラスの<code>timeout</code>メソッドに、<code>{}</code>を渡す。<br> <syntaxhighlight lang="c++"> timer->timeout({}); </syntaxhighlight> <br> 一般的に、<code>timeout</code>シグナルを接続したスロット関数では、以降変更しない場合、<br> <code>QTimer</code>クラスの<code>start</code>メソッドを実行する前に、直接スロット関数を1度呼ぶ。<br> しかし、接続するスロット関数を動的に変更する場合、<code>timeout</code>メソッドを呼ぶだけの方が便利である。<br> <br> 以下の例では、プッシュボタンとラベルを配置して、プッシュボタンを押下した直後にタイマを開始している。<br> そして、プッシュボタンを押下し続けている間、1秒毎に1増加している。<br> <syntaxhighlight lang="c++"> // MainWindow.hファイル #include <QMainWindow> #include <memory> class MainWindow : public QMainWindow { Q_OBJECT private: Ui::MainWindow *ui; std::unique_ptr<QTimer> m_Timer; int m_Val; private: void timerFunc() { m_Val++; ui->label->setText(QString::number(m_Val)); } public: explicit MainWindow(QWidget *parent = nullptr) : QMainWindow(parent), ui(new Ui::MainWindow), m_Timer(nullptr), m_Val(0) { ui->setupUi(this); ui->label->setText(QString::number(val)); m_Timer = std::make_unique<QTimer>(this); connect(m_Timer, &QTimer::timeout, this, &MainWindow::timerFunc); } ~MainWindow() { delete ui; } private slots: void on_pushButton_pressed() { m_Timer->timeout({}); m_Timer->start(1000); } void on_pushButton_released() { m_Timer->stop(); } }; </syntaxhighlight> <br> <syntaxhighlight lang="c++"> // main.cppファイル #include "MainWindow.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); MainWindow window; window.show(); return app.exec(); } </syntaxhighlight> <br><br> == タイマを使用したスリープ == 以下の例では、<code>QEventLoop</code>クラスを使用したスリープ処理である。<br> これは、CPUに負荷を掛けずにイベントシステムを使用してタイマを終了することができる。<br> <syntaxhighlight lang="c++"> #include <QTimer> void MainWindow::Delay(int ms) { QEventLoop loop; QTimer Timer(this); connect(&Timer, &QTimer::timeout, &loop, &QEventLoop::quit); Timer.start(ms); loop.exec(); } </syntaxhighlight> <br><br> __FORCETOC__ [[カテゴリ:Qt]]
Qtの基礎 - タイマ
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse