我是qt的新手,想要创建一个发送整数信号的线程,我有一个接收信号的主窗口,我确信信号是在我用cout看到的时候发送的,但是当我想发送收到的信息时放置在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:
#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.什么错了?
答案 0 :(得分: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 Concurrent模块在可能的情况下跨多个线程并行化计算。