如果从 QRunnable 或其他线程调用,Qt 信号和槽将不起作用
Qt signal and slots do not work if called from QRunnable or another thread
我正在尝试学习如何在 Qt 中使用多线程并将其用于 QtWidget 应用程序。所以我设置了这个简单的测试用例。
主窗口
此表单有一些按钮,每个按钮将执行另一个表单(与此相关的对话框)。
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->btnShowCalibrationDialog, &QPushButton::clicked,
this, [&](){
CalibrationDialog dlg;
dlg.exec();
});
}
MainWindow::~MainWindow()
{
delete ui;
}
CalibrationDialog 这个对话框有一个 QPushButton
和一个 QTextEdit
。单击按钮后,我将 运行 一个 QRunnable class(下一个!)
calibrationdialog.h(内含和守卫都省了!)
class CalibrationDialog : public QDialog
{
Q_OBJECT
public:
explicit CalibrationDialog(QWidget *parent = nullptr);
~CalibrationDialog();
public slots:
void onBeginWorkRequested();
void onReceiveData(int data);
private:
Ui::CalibrationDialog *ui;
};
calibrationdialog.cpp
#include "worker.h"
CalibrationDialog::CalibrationDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::CalibrationDialog)
{
ui->setupUi(this);
connect(ui->btnBegin, &QPushButton::clicked,
this, &CalibrationDialog::onBeginWorkRequested);
}
CalibrationDialog::~CalibrationDialog()
{
delete ui;
}
void CalibrationDialog::onBeginWorkRequested()
{
qDebug() << "CalibrationDialog::onBeginWorkRequested()" << "on" << QThread::currentThreadId();
Worker* worker = new Worker();
QThreadPool* pool = QThreadPool::globalInstance();
connect(worker, &Worker::reportProgress,
this, &CalibrationDialog::onReceiveData);
pool->start(worker);
pool->waitForDone();
}
void CalibrationDialog::onReceiveData(int data)
{
ui->teResults->append(QString::number(data));
ui->teResults->ensureCursorVisible();
}
Worker 这是一些 运行nable...我想报告进度,以便它以响应方式显示在对话框的文本编辑中!
worker.h
class Worker : public QObject, public QRunnable
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
void run() override;
private:
int mProgress = 0;
signals:
void reportProgress(int progress);
};
worker.cpp
Worker::Worker(QObject *parent) : QObject(parent)
{
}
void Worker::run()
{
qDebug() << "Worker is running #" << QThread::currentThreadId();
while(true) {
mProgress += 100;
emit reportProgress(mProgress);
QThread::msleep(500);
}
}
我在调试器中看到控件进入了 while 循环...但是信号没有被对话框处理!我的意思是 textedit 保持为空!
我尝试阅读文档并在线搜索...我得出的结论是我的问题在于线程亲和力的荒地...但我不知道是否是这种情况,如果是,如何解决它。请协助!
删除 pool->waitForDone();
,切勿在 GUI 中使用 waitForX 方法,因为它们会阻止信号执行其工作。
我正在尝试学习如何在 Qt 中使用多线程并将其用于 QtWidget 应用程序。所以我设置了这个简单的测试用例。
主窗口 此表单有一些按钮,每个按钮将执行另一个表单(与此相关的对话框)。
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->btnShowCalibrationDialog, &QPushButton::clicked,
this, [&](){
CalibrationDialog dlg;
dlg.exec();
});
}
MainWindow::~MainWindow()
{
delete ui;
}
CalibrationDialog 这个对话框有一个 QPushButton
和一个 QTextEdit
。单击按钮后,我将 运行 一个 QRunnable class(下一个!)
calibrationdialog.h(内含和守卫都省了!)
class CalibrationDialog : public QDialog
{
Q_OBJECT
public:
explicit CalibrationDialog(QWidget *parent = nullptr);
~CalibrationDialog();
public slots:
void onBeginWorkRequested();
void onReceiveData(int data);
private:
Ui::CalibrationDialog *ui;
};
calibrationdialog.cpp
#include "worker.h"
CalibrationDialog::CalibrationDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::CalibrationDialog)
{
ui->setupUi(this);
connect(ui->btnBegin, &QPushButton::clicked,
this, &CalibrationDialog::onBeginWorkRequested);
}
CalibrationDialog::~CalibrationDialog()
{
delete ui;
}
void CalibrationDialog::onBeginWorkRequested()
{
qDebug() << "CalibrationDialog::onBeginWorkRequested()" << "on" << QThread::currentThreadId();
Worker* worker = new Worker();
QThreadPool* pool = QThreadPool::globalInstance();
connect(worker, &Worker::reportProgress,
this, &CalibrationDialog::onReceiveData);
pool->start(worker);
pool->waitForDone();
}
void CalibrationDialog::onReceiveData(int data)
{
ui->teResults->append(QString::number(data));
ui->teResults->ensureCursorVisible();
}
Worker 这是一些 运行nable...我想报告进度,以便它以响应方式显示在对话框的文本编辑中!
worker.h
class Worker : public QObject, public QRunnable
{
Q_OBJECT
public:
explicit Worker(QObject *parent = nullptr);
void run() override;
private:
int mProgress = 0;
signals:
void reportProgress(int progress);
};
worker.cpp
Worker::Worker(QObject *parent) : QObject(parent)
{
}
void Worker::run()
{
qDebug() << "Worker is running #" << QThread::currentThreadId();
while(true) {
mProgress += 100;
emit reportProgress(mProgress);
QThread::msleep(500);
}
}
我在调试器中看到控件进入了 while 循环...但是信号没有被对话框处理!我的意思是 textedit 保持为空!
我尝试阅读文档并在线搜索...我得出的结论是我的问题在于线程亲和力的荒地...但我不知道是否是这种情况,如果是,如何解决它。请协助!
删除 pool->waitForDone();
,切勿在 GUI 中使用 waitForX 方法,因为它们会阻止信号执行其工作。