2016-12-05 41 views
0

我是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.什么是错的?

回答

2

您需要调用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并行模块来并行计算跨多个线程。

+0

预先感谢您!它解决了我的问题:) –