接收到 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 模块来跨多个线程并行计算。
我是 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 模块来跨多个线程并行计算。