Qt子线程刷新主线程界面

  1. 问题:

之前做了一个界面,16个线程会刷新主界面的控件,莫名其妙的就崩溃了,还是偶发性,也不知道啥原因,看Qt报的错误信息是“QWidget::repaint: Recursive repaint detected”

  1. 查找原因:
    看了两个Stack Overflow的问答:

https://stackoverflow.com/questions/31180660/qwidgetrepaint-recursive-repaint-detected

https://stackoverflow.com/questions/25733142/qwidgetrepaint-recursive-repaint-detected-when-updating-progress-bar
其中一个翻译页面。
Qt子线程刷新主线程界面_第1张图片
意思非常的明确,就是子线程不能刷GUI。

  1. 解决方案
    用信号槽实现。
connect(this,SIGNAL(UpdateLabelText()), thiss, SLOT(slotUpdateLabelText()));

QObject::connect(
const QObject * sender, //发送者
const char * signal, //信号
const QObject * receiver, //接受者
const char * method, //槽函数
Qt::ConnectionType type = Qt::AutoConnection)

  1. 测试程序

示例如下:

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 

QT_BEGIN_NAMESPACE
namespace Ui {
      class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
     
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
    void setLabelText(const QString &text);
public slots:
    void on_pushButton_start_clicked();

    void on_pushButton_stop_clicked();

private slots:


private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "updateuithread.h"
#include 
#include 
#include 
int isRun;

void updateLabel(MainWindow *p)
{
     
    int i=0;
    QString str="i="+QString::number(i);
    while(true)
    {
     
        p->setLabelText(str);
        i++;
        QThread::sleep(200);
    }

}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
     
    ui->setupUi(this);
    connect(this,SIGNAL(clicked()),this,SLOT(on_pushButton_start_clicked()));
    connect(this,SIGNAL(clicked()),this,SLOT(on_pushButton_stop_clicked()));

}


MainWindow::~MainWindow()
{
     
    delete ui;
}
void startThread()
{
     

}

void MainWindow::setLabelText(const QString &text)
{
     
    ui->label->setText(text);
    ui->label->repaint();
}


void MainWindow::on_pushButton_start_clicked()
{
     
    UpdateUIThread *thread=new UpdateUIThread(this); 
    thread->start();
    isRun=1;
    /*std::thread *pThread=new std::thread(updateLabel,this); //开启子线程刷新界面
    pThread->detach();*/
}

void MainWindow::on_pushButton_stop_clicked()
{
     
    isRun=0;
}

updateuithread.h

#ifndef UPDATEUITHREAD_H
#define UPDATEUITHREAD_H
#include "mainwindow.h"
#include 

class UpdateUIThread : public QThread
{
     
    Q_OBJECT
public:
    UpdateUIThread();
    UpdateUIThread(MainWindow *gui);
    ~UpdateUIThread();

    void run() override;
signals:
    void updateLable(const QString &text);
public slots:
    void slotUpdateUI(const QString &text);

public:
    MainWindow *pMain;
};

#endif // UPDATEUITHREAD_H

updateuithread.cpp

#include "updateuithread.h"
extern int isRun;
int i=0;
UpdateUIThread::UpdateUIThread()
{
     

}
UpdateUIThread::~UpdateUIThread()
{
     

}

UpdateUIThread::UpdateUIThread(MainWindow *gui)
{
     
    pMain=gui;
    connect(this,SIGNAL(updateLable(const QString &)),this,SLOT(slotUpdateUI(const QString &)));
}
void UpdateUIThread::run()
{
     
    QString str;
    while(isRun)
    {
     
        str="i="+QString::number(i);
        emit updateLable(str);
        msleep(100);
        i++;
    }
}
void UpdateUIThread::slotUpdateUI(const QString &text)
{
     
    //QString str="i="+QString::number(i);
    pMain->setLabelText(text);//(str);
    //i++;
}

Qt子线程刷新主线程界面_第2张图片
可以看到结果是正常的了。

你可能感兴趣的:(QT,QT,线程,子线程,主界面)