[英]QThreading in QT and update GUI at the same time
您好,我正在嘗試將我的結果從一個線程打印到textBrower
中的qtwidget QT
,但我不能,要么出現錯誤,要么程序無法編譯,還有其他方法嗎? 如何更改textBrowser
之外的 textBrowser?
PS 順便說一句,我需要在線程內循環,因為實際上我在最終程序中從uart
獲取了一些數據(在這段代碼中,我只想打印"lol"
,最終我想用其他一些獲取數據的代碼來更改它)所以我不能來跳出循環最終我想使用另一個庫中的一些過程並實時顯示結果
bool stop;
out::out(QWidget *parent) :
QWidget(parent),
ui(new Ui::out)
{
ui->setupUi(this);
ui->textBrowser->setText("lol");
}
out::~out()
{
delete ui;
}
///////////////////////////////////////////////
class t : public out, public QThread
{
public:
void run()
{
while(1){
qDebug()<<"hi"<<i;
// ui->textBrowser->setText("lol"); I tried to use this but it didnt worked
if(stop==true){
QThread::exec();
}
}
}
};
void mamad1(void){ //this function get called from another cpp file and its for starting the thread
stop=false;
t *b = new t;
b->start();
}
void out::on_pushButton_clicked() // a push button to stop the thread
{
stop=true;
}
我嘗試將 out.h 文件中的 ui 設為公共屬性並使用ui->textBrowser->setText("lol");
但它沒有工作程序凍結,我得到這個error: (Parent is QTextDocument(0x208d812a510), parent's thread is QThread(0x208d6816de0), current thread is QThread(0x208dac94e10)
我也嘗試使用connect()
但沒有用,或者我沒有正確使用它
QT這個GUI線程的概念叫做主線程。 這個線程有一個事件隊列。 通常,此事件隊列由內部和外部事件填充。 此外,線程之間的隊列是一種高效的線程通信方式。 工作線程也是如此。 當您通過工作線程調用 start 方法時,它們的信號隊列將被創建並准備好被相應的線程使用。
讓我們回到你的問題。 解決方法很簡單。 從您的工作線程,您可以向主線程發送一個信號。 主線程將看到這個修改 GUI 項目的事件,並將這個信號/事件轉發到負責采取相應行動的插槽。 只需在您的工作線程中定義一個信號,然后將您的主線程連接到具有給定插槽的該信號。
主窗口.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <MyWorkerThread.h>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void setWorkerThread(MyWorkerThread* thread);
void connectToSignals();
public slots:
void handleTextBoxSignal(const QString& text);
private:
Ui::MainWindow *ui;
MyWorkerThread* m_worker_thread{nullptr};
};
#endif // MAINWINDOW_H
主窗口.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
void MainWindow::setWorkerThread(MyWorkerThread* thread)
{
m_worker_thread = thread;
}
void MainWindow::connectToSignals()
{
QObject::connect(m_worker_thread,
SIGNAL(changeTextOnUI(QString)),
this,
SLOT(handleTextBoxSignal(QString)));
}
void MainWindow::handleTextBoxSignal(const QString& text)
{
qDebug() << "Text box change signal received with text: " << text;
auto text_box = findChild<QTextEdit*>("myTxtEdit");
if(text_box != nullptr)
{
text_box->setText(text);
}
}
MainWindow::~MainWindow()
{
delete ui;
}
我的工作線程.h
#ifndef MYWORKERTHREAD_H
#define MYWORKERTHREAD_H
#include <QObject>
#include <QThread>
class MyWorkerThread : public QThread
{
Q_OBJECT
public:
MyWorkerThread(QObject* parent = nullptr);
void stopThread();
signals:
void changeTextOnUI(const QString& text);
private:
void run() override;
bool m_exit{false};
};
#endif // MYWORKERTHREAD_H
我的工作線程.cpp
#ifndef MYWORKERTHREAD_H
#define MYWORKERTHREAD_H
#include <QObject>
#include <QThread>
class MyWorkerThread : public QThread
{
Q_OBJECT
public:
MyWorkerThread(QObject* parent = nullptr);
void stopThread();
signals:
void changeTextOnUI(const QString& text);
private:
void run() override;
bool m_exit{false};
};
#endif // MYWORKERTHREAD_H
主.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
MyWorkerThread* worker_thread = new MyWorkerThread();
w.setWorkerThread(worker_thread);
w.connectToSignals();
worker_thread->start();
w.show();
return a.exec();
}
在上面的代碼中,您看到了問題的完整解決方案。 在工作線程中,我們遞增一個 static 計數器並將它與一個字符串連接起來,然后將它發送到管理 UI 元素的主線程。 我們發出一個信號,這個信號落在插槽上。 這樣主線程每 5 秒更新一次屏幕上的文本框。 工作線程在每次迭代時休眠 5 秒。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.