参考記事:
https://blog.csdn.net/u012635648/article/details/89504115
1. 非同期スレッドクラスの設計
スレッドオブジェクトの破棄をスレッドのライフサイクルの終了時に通知します。
スレッドオブジェクトはヒープ領域でのみ作成でき、外部から明示的に破棄することはできません。
run 関数の最後で deleteLater () 関数を呼び出します。
スレッド関数はスレッドオブジェクトの破棄をアクティブに要求します。
使用シーン:
スレッドのライフサイクルが制御できず、バックグラウンドで長時間実行する必要があるスレッドです。
#ifndef ASYNCTHREAD_H
#define ASYNCTHREAD_H
#include <QThread>
class AsyncThread : public QThread
{
Q_OBJECT
protected:
void run()
{
deleteLater();
}
explicit AsyncThread(QObject* parent = 0):QThread(parent)
{
}
~AsyncThread()
{
}
public:
static AsyncThread* newThread(QObject* parent = 0)
{
return new AsyncThread(parent);
}
};
#endif // ASYNCTHREAD_H
2.QThread のサブクラス化
QThread の 2 つの使用方法:
(1)イベントループを使用しない場合
A、QThread をサブクラス化する
B、run 関数をオーバーライドし、run 関数内に while または for の無限ループを作成する
C、無限ループの終了を制御するためのフラグを設定する。
ファイルのコピー、ネットワークデータの読み取りなど、バックグラウンドで長時間実行する耗時操作に適しています。
(2)イベントループを使用する。
A、QThread をサブクラス化する
B、run 関数をオーバーライドし、QThread::exec () を呼び出してスレッドのイベントループを開始する
C、サブクラスにシグナルとスロットを定義する。スロット関数は新しく開かれたスレッドで実行されないため、コンストラクタで moveToThread (this) を呼び出します。
ファイルの読み書き、データベースの読み書きなどのトランザクション操作に適しています。
3. シグナルとスロットの方法
マルチスレッドと GUI コンポーネントの通信を解決するためのシグナルとスロットの使用方法:
A、サブスレッドで GUI コンポーネントの更新シグナルを定義します。
B、メインウィンドウクラスで GUI コンポーネントの更新スロット関数を定義します。
C、非同期方式で更新シグナルをスロット関数に接続します。
サブスレッドはシグナルを送信して GUI コンポーネントを更新し、すべての GUI コンポーネントオブジェクトは GUI スレッド(メインスレッド)に依存します。
サブスレッドによる GUI の状態の更新は、サブスレッドが信号を送信してメインスレッドに GUI の更新要求を通知することによって行われます。メインスレッドは具体的な信号と信号パラメータに基づいて GUI コンポーネントを変更します。
シグナルとスロットを使用して、サブスレッドでメインインターフェースの進捗バーの進捗表示情報を更新します。
ワーカースレッドクラス:
#ifndef WORKTHREAD_H
#define WORKTHREAD_H
#include <QThread>
class WorkThread : public QThread
{
Q_OBJECT
signals:
void signalProgressValue(int value);
protected:
void run()
{
work();
exec();
}
public:
WorkThread()
{
m_stop = false;
moveToThread(this);
}
void work()
{
for(int i = 0; i < 11; i++)
{
emit signalProgressValue(i*10);
sleep(1);
}
}
};
#endif // WORKTHREAD_H
メインインターフェースクラス:
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QProgressBar>
#include "WorkThread.h"
class Widget : public QWidget
{
Q_OBJECT
QProgressBar* m_progress;//進捗バー
WorkThread* m_thread;//ワーカースレッド
public:
Widget(QWidget *parent = 0):QWidget(parent)
{
m_progress = new QProgressBar(this);
m_progress->move(10, 10);
m_progress->setMinimum(0);
m_progress->setMaximum(100);
m_progress->setTextVisible(true);
m_progress->resize(100, 30);
m_thread = new WorkThread();
m_thread->start();
connect(m_thread, SIGNAL(finished()), m_thread, SLOT(deleteLater()));
//ワーカースレッドのシグナルをインターフェースのスロット関数に接続する
connect(m_thread, SIGNAL(signalProgressValue(int)), this, SLOT(onProgress(int)));
}
~Widget()
{
}
protected slots:
void onProgress(int value)
{
m_progress->setValue(value);
}
};
#endif // WIDGET_H
メイン関数:
#include "Widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}