提示:文章寫完后,目錄可以自動(dòng)生成,如何生成可參考右邊的幫助文檔
前言
提示:這里可以添加本文要記錄的大概內(nèi)容:
工程需要Qt多線程+opencv 結(jié)合信號(hào)與槽讀取和顯示圖像
提示:以下是本篇文章正文內(nèi)容,下面案例可供參考
一、例程
加入了信號(hào)與槽機(jī)制來(lái)處理多線程中的圖像數(shù)據(jù):
- 創(chuàng)建工作線程類:首先創(chuàng)建一個(gè)工作線程類,它從QThread繼承并包含一個(gè)信號(hào)來(lái)發(fā)送圖像數(shù)據(jù)。
class WorkerThread : public QThread
{
Q_OBJECT
public:
void run() override {
// 讀取圖像數(shù)據(jù)
cv::Mat image = cv::imread("path_to_image.jpg");
emit imageReady(image); // 發(fā)出信號(hào),傳遞圖像數(shù)據(jù)
}
signals:
void imageReady(const cv::Mat &image); // 信號(hào),傳遞圖像數(shù)據(jù)
};
- 創(chuàng)建主窗口類:創(chuàng)建一個(gè)主窗口類,其中包含一個(gè)槽函數(shù)來(lái)接收工作線程發(fā)出的信號(hào),并在主線程中顯示圖像。
class MainWindow : public QObject {
Q_OBJECT
public:
MainWindow() {
// 創(chuàng)建工作線程實(shí)例并啟動(dòng)
WorkerThread *thread = new WorkerThread();
connect(thread, &WorkerThread::imageReady, this, &MainWindow::displayImage); // 連接信號(hào)和槽
thread->start();
}
public slots:
void displayImage(const cv::Mat &image) {
// 在主線程中顯示圖像
cv::imshow("Image Display", image);
cv::waitKey(0); // 等待用戶按鍵,保持顯示狀態(tài)
}
};
-
連接信號(hào)和槽:在主窗口類的構(gòu)造函數(shù)中,我們使用
connect
函數(shù)將工作線程的imageReady
信號(hào)連接到主窗口類的displayImage
槽。這樣,當(dāng)工作線程完成圖像讀取并發(fā)出imageReady
信號(hào)時(shí),displayImage
槽函數(shù)將被自動(dòng)調(diào)用。 - 主函數(shù):最后,在主函數(shù)中創(chuàng)建主窗口類的實(shí)例并運(yùn)行應(yīng)用程序。
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
MainWindow mainWindow;
return a.exec();
}
這個(gè)例子展示了如何使用Qt的信號(hào)與槽機(jī)制在多線程環(huán)境中安全地處理圖像數(shù)據(jù)。工作線程讀取圖像數(shù)據(jù)并通過(guò)信號(hào)發(fā)送,主線程通過(guò)槽函數(shù)接收并顯示圖像,確保了線程安全和正確的同步。
二、線程的開(kāi)啟和關(guān)閉
在Qt中,線程的開(kāi)始和關(guān)閉可以通過(guò)以下方式實(shí)現(xiàn):
-
啟動(dòng)線程:
- 定義工作類:通常,你會(huì)創(chuàng)建一個(gè)類來(lái)繼承
QThread
,并重寫其run()
函數(shù)。在這個(gè)函數(shù)中,你可以定義線程應(yīng)該執(zhí)行的代碼。 - 實(shí)例化并啟動(dòng)線程:在主函數(shù)中,你可以實(shí)例化這個(gè)工作類,并調(diào)用其
start()
方法來(lái)啟動(dòng)線程。
- 定義工作類:通常,你會(huì)創(chuàng)建一個(gè)類來(lái)繼承
-
關(guān)閉線程:
-
優(yōu)雅地關(guān)閉線程:在線程的
run()
函數(shù)中,你可以使用一個(gè)標(biāo)志變量(如volatile bool m_toStop
)來(lái)判斷是否需要從run()
函數(shù)返回。在線程運(yùn)行的過(guò)程中,你可以檢查這個(gè)標(biāo)志變量的值來(lái)決定是否需要停止線程。當(dāng)線程需要停止時(shí),設(shè)置這個(gè)標(biāo)志變量為true
。在線程的run()
函數(shù)結(jié)束時(shí),線程自然死亡。 -
強(qiáng)制關(guān)閉線程:如果需要立即停止線程,可以使用
thread->quit()
或thread->wait()
方法。前者會(huì)嘗試停止正在運(yùn)行的線程,后者會(huì)等待線程結(jié)束。
-
優(yōu)雅地關(guān)閉線程:在線程的
請(qǐng)注意,關(guān)閉線程時(shí)需要確保線程已經(jīng)完成了其任務(wù),避免資源泄露或數(shù)據(jù)不一致的問(wèn)題。同時(shí),處理多線程時(shí)需要考慮到線程同步和互斥的問(wèn)題,確保線程安全地訪問(wèn)共享資源。
以下是一個(gè)使用Qt多線程的詳細(xì)例程:
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QTimer>
class Worker : public QThread
{
Q_OBJECT
public:
Worker() {}
void run() override {
int i = 0;
while (!isInterruptionRequested()) {
qDebug() << "Thread is running" << ++i;
QThread::sleep(1); // 模擬耗時(shí)操作
}
}
};
class MainWindow : public QObject {
Q_OBJECT
public:
MainWindow(QObject *parent = nullptr) : QObject(parent) {
Worker *worker = new Worker();
connect(worker, &Worker::started, this, &MainWindow::onWorkerStarted);
connect(worker, &Worker::finished, this, &MainWindow::onWorkerFinished);
worker->start(); // 啟動(dòng)線程
}
public slots:
void onWorkerStarted() { qDebug() << "Worker started"; }
void onWorkerFinished() { qDebug() << "Worker finished"; }
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
MainWindow mainWindow;
return a.exec();
}
這個(gè)例程中,我們創(chuàng)建了一個(gè)Worker
類來(lái)繼承QThread
,并重寫了其run()
函數(shù)。在run()
函數(shù)中,我們使用一個(gè)循環(huán)來(lái)模擬線程的持續(xù)運(yùn)行,并每隔1秒打印一條消息。我們還定義了一個(gè)MainWindow
類,其中包含一個(gè)工作線程的實(shí)例。通過(guò)連接工作線程的started
和finished
信號(hào)到主窗口類的槽函數(shù),我們可以在工作線程開(kāi)始和結(jié)束時(shí)執(zhí)行特定的操作。最后,在主函數(shù)中,我們創(chuàng)建了主窗口類的實(shí)例并運(yùn)行應(yīng)用程序。
三、判斷線程是否還在運(yùn)行
在Qt中,判斷線程是否仍在運(yùn)行可以通過(guò)檢查線程的狀態(tài)來(lái)實(shí)現(xiàn)。Qt提供了QThread::isRunning()
函數(shù),該函數(shù)返回一個(gè)布爾值,表示線程是否正在運(yùn)行。
以下是一個(gè)簡(jiǎn)單的示例代碼,演示如何使用isRunning()
函數(shù)來(lái)判斷線程是否仍在運(yùn)行:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-826158.html
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
class MyThread : public QThread {
Q_OBJECT
public:
MyThread(QObject *parent = nullptr) : QThread(parent) {}
void run() override {
// 線程執(zhí)行的代碼
qDebug() << "Thread started";
// ...
// 線程結(jié)束前的操作
qDebug() << "Thread finished";
exit(0); // 結(jié)束線程
}
};
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
MyThread thread;
thread.start(); // 啟動(dòng)線程
// 檢查線程是否仍在運(yùn)行
while (thread.isRunning()) {
qDebug() << "Thread is still running";
QThread::sleep(1); // 等待一段時(shí)間,避免過(guò)度消耗CPU資源
}
qDebug() << "Thread has finished";
return a.exec();
}
在上面的代碼中,我們創(chuàng)建了一個(gè)自定義的MyThread
類,它繼承自QThread
。在run()
函數(shù)中,我們定義了線程要執(zhí)行的代碼。在主函數(shù)中,我們創(chuàng)建了MyThread
的實(shí)例,并調(diào)用其start()
方法來(lái)啟動(dòng)線程。然后,我們使用一個(gè)while
循環(huán)來(lái)檢查線程是否仍在運(yùn)行。如果線程仍在運(yùn)行,循環(huán)會(huì)繼續(xù)執(zhí)行并打印消息。在每次循環(huán)迭代之間,我們使用QThread::sleep(1)
來(lái)等待一段時(shí)間,以避免過(guò)度消耗CPU資源。當(dāng)線程結(jié)束時(shí),isRunning()
函數(shù)將返回false
,循環(huán)將停止執(zhí)行。最后,我們打印一條消息表示線程已經(jīng)完成。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-826158.html
總結(jié)
到了這里,關(guān)于【Qt 多線程+opencv 讀取和顯示圖像】的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!