2016-12-05 43 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

預先感謝您!它解決了我的問題:) –