Qt信号已收到,但UI没有显示出来
问题描述:
我是qt的新手,想要创建一个发送整数信号的线程,并且我有一个接收信号的主窗口,并且我确信信号按照我用cout看到它,但是当我想将接收到的号码发送到置于ui中的spinbox(或标签)时,主线程被卡住并且不显示任何内容。Qt信号已收到,但UI没有显示出来
这里是我的线程类:螺纹
#ifndef MYTHREAD_H
#define MYTHREAD_H
#include <QThread>
#include <QtCore>
class MyThread : public QThread
{
Q_OBJECT
public:
explicit MyThread(QObject *parent = 0);
void run();
bool Stop;
signals:
void NumberChanged(int);
public slots:
};
#endif // MYTHREAD_H
CPP文件:
#include "mythread.h"
#include <QtCore>
MyThread::MyThread(QObject *parent) :
QThread(parent)
{
}
void MyThread::run()
{
for(int i=0;i<2000000;i++){
QMutex m;
emit NumberChanged(i);
QThread::msleep(100);
}
}
mainwindow.h:
终于mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <iostream>
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
mthread = new MyThread(this);
connect(mthread,SIGNAL(NumberChanged(int)),this,SLOT(onNumberChanged(int)));
mthread->property(Q)
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::onNumberChanged(int num)
{
cout << num << endl;
ui->spinBox->setValue(num);
}
void MainWindow::on_pushButton_clicked()
{
mthread->run();
}
当我运行这个,整数值是由cout显示,但spinbox或标签不会改变,直到数量达到2000000.什么是错的?
答
您需要调用start()
方法启动线程,而不是run()
方法。你的线程实现错误地使run()
成为一个公共方法:这可以让你犯这个错误 - 否则它将不可能通过构造。 run()
应该是protected
,而不是public
。
当请求线程中断时(c.f. QThread::requestInterruption()
和QThread::isInterruptionRequested()
),您可能还想中断循环。您还需要随时使线可破坏,以便在退出应用程序时,线可以干净地卷起来。
最后,您希望将线程与用户界面分开:窗口不需要知道线程,反之亦然。它们应通过兼容的接口连接,例如通过信号和插槽。
因此,我首先将您的代码转换为:
#include <QtWidgets>
class MyThread : public QThread
{
Q_OBJECT
public:
using QThread::QThread;
~MyThread() { requestInterruption(); wait(); }
void run() override {
for(int i=0; i<2000000 && !isInterruptionRequested(); i++) {
emit numberChanged(i);
QThread::msleep(100);
}
}
Q_SIGNAL void numberChanged(int);
};
class Window : public QWidget
{
Q_OBJECT
QVBoxLayout m_layout{this};
QPushButton m_start{"Start"};
QPushButton m_stop{"Stop"};
QSpinBox m_box;
public:
Window() {
m_layout.addWidget(&m_start);
m_layout.addWidget(&m_stop);
m_layout.addWidget(&m_box);
connect(&m_start, &QPushButton::clicked, this, &Window::reqStart);
connect(&m_stop, &QPushButton::clicked, this, &Window::reqStop);
}
Q_SIGNAL void reqStart();
Q_SIGNAL void reqStop();
Q_SLOT void setNumber(int n) {
m_box.setValue(n);
}
};
int main(int argc, char **argv) {
QApplication app{argc, argv};
MyThread t;
Window w;
QObject::connect(&w, &Window::reqStart, &t, [&t]{ t.start(); });
QObject::connect(&t, &MyThread::numberChanged, &w, &Window::setNumber);
QObject::connect(&w, &Window::reqStop, &t, &MyThread::requestInterruption);
w.show();
return app.exec();
}
#include "main.moc"
的第二次转型将涉及循环进入一个QObject
,并使用一个通用的安全线来承载它 - 这个过程在this answer详细。
如果可能的话,第三种转换可能会涉及到使用Qt并行模块来并行计算跨多个线程。
预先感谢您!它解决了我的问题:) –