接收到 Qt 信号但 ui 不显示

Qt signal is recieved but ui doesnt show it

我是 qt 的新手,想创建一个发送整数信号的线程,我有一个接收信号的主窗口,我确信信号已传递,因为我使用 cout 来查看它,但是当我想将收到的号码发送到位于 ui 中的旋转框(或标签),主线程被卡住并且不显示任何内容。

这是我的话题 class:

#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:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "mythread.h"

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    MyThread *mthread;

private:
    Ui::MainWindow *ui;

private slots:
    void on_pushButton_clicked();

public slots:
    void onNumberChanged(int num);
};

#endif // 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 显示,但旋转框或标签根本不会改变,直到数字达到 2000000。有什么问题吗?

您需要通过调用其 start() 方法而不是 run() 方法来启动线程。您的线程实现错误地使 run() 成为 public 方法:这使您犯了这个错误 - 否则构造是不可能的。 run() 应该是 protected,而不是 public

您可能还想在请求线程中断时中断循环(c.f。QThread::requestInterruption()QThread::isInterruptionRequested())。您还需要使线程在任何时候都可破坏,这样当您退出应用程序时,线程就会干净地结束。

最后,您希望将线程与用户界面分离:window 不需要了解线程,反之亦然。它们应该通过兼容的接口连接,例如通过信号和槽。

因此,我首先将您的代码转换为:

#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,并使用通用安全线程来托管它 - 该过程在 中有详细说明。

如果可能,第三个转换可能涉及使用 Qt Concurrent 模块来跨多个线程并行计算。