QT |
您所在的位置:网站首页 › qtmovetothread发送信号出现线程对象收不到的情况 › QT |
目录 1、问题简介 2、解决方案 3、解决示例 1、问题简介在实际开发中,我们经常会进行一些比较复杂的计算和算法实现,或者是在某些特定的情况下会实例化一些类。这些操作都是很消耗时间的,如果在此时需要进行一些UI的渲染的话,这些耗时操作就会阻塞渲染线程,导致无法达到想要的效果。 例如,我们想要在进行计算时,显示一个等待动画界面,直到计算结果出来后再关闭掉这个等待界面。但是这就会导致等待界面渲染阻塞,而当计算结果出来后又将界面关闭,带来的用户使用效果就是好像卡住了一样。 问题代码示例: (1).h文件 #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include #include #include QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); void comIntensive(); protected: void mousePressEvent(QMouseEvent *e) override; private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H(2).cpp文件 #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); QMovie *gif = new QMovie(); gif->setFileName(":/gif.gif"); ui->label->setMovie(gif); // 设置QLabel的背景为透明 ui->label->setStyleSheet("background-color: transparent;"); gif->start(); ui->label->hide(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::comIntensive() { QList res; do{ double resInf = ((qrand() * 1.00)/(RAND_MAX * 10)) * 1000.00; if(res.isEmpty()){ res.append(resInf); } else{ if(!res.contains(resInf)){ res.append(resInf); } } } while(!res.isEmpty() && res.size() plainTextEdit->appendHtml(QString::number(var,'f',2)); } } void MainWindow::mousePressEvent(QMouseEvent *e) { if(e->button() == Qt::LeftButton){ ui->plainTextEdit->clear(); ui->label->show(); comIntensive(); ui->label->hide(); } }在以上示例中,我希望生成10000个(0,100)之间的不重复的含有两位小数的double类型的浮点数,在生成期间我采用QMovie来显示一个gif动画,这样在生成期间就可以有一个等待动画界面。 但是在实际操作时,由于线程阻塞而导致没有达到想要的效果,反而给用户一种卡顿的感觉。 2、解决方案针对以上问题,有两个方法可以解决: ①开启子线程,将QMovie动画交给子线程来处理,而主线程则主要负责进行数据的计算和产生,这样的话就能够解决线程阻塞的问题。但是这样做也有一些问题,一般而言,在qt中我们会将有关UI渲染的东西都放置在主线程内,而不是通过子线程去实现。 ②开启子线程,将复杂计算内容交给子线程来处理,主线程主要进行UI的渲染操作,这样同样能够解决线程阻塞的问题,同时这样也更符合我们的生产消费设计模式。 3、解决示例(1).h文件 #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include #include #include #include #include #include "threadlock.h" QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); // void comIntensive(); ThreadLock *mythread; QMovie *gif; protected: void mousePressEvent(QMouseEvent *e) override; private: Ui::MainWindow *ui; public slots: void onThreadFinished(); }; #endif // MAINWINDOW_H #ifndef THREADLOCK_H #define THREADLOCK_H #include #include #include enum SM_Thread{ TYPE_INFO, TYPE_DEG, TYPE_RES, TYPR_WAR }; Q_NAMESPACE Q_ENUM_NS(SM_Thread) class ThreadLock : public QThread { Q_OBJECT public: ThreadLock(); ~ThreadLock(); QList res; SM_Thread from = TYPR_WAR; void setLogic(SM_Thread var); void comIntensive(); protected: void run() override; private: QReadWriteLock Lock; }; #endif // THREADLOCK_H(2).cpp文件 #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); gif = new QMovie(); gif->setFileName(":/gif.gif"); ui->label->setMovie(gif); // 设置QLabel的背景为透明 ui->label->setStyleSheet("background-color: transparent;"); gif->start(); ui->label->hide(); } MainWindow::~MainWindow() { delete ui; } //void MainWindow::comIntensive() //{ // QList res; // do{ // double resInf = ((qrand() * 1.00)/(RAND_MAX * 10)) * 1000.00; // if(res.isEmpty()){ // res.append(resInf); // } // else{ // if(!res.contains(resInf)){ // res.append(resInf); // } // } // } // while(!res.isEmpty() && res.size() plainTextEdit->appendHtml(QString::number(var,'f',2)); // } //} void MainWindow::mousePressEvent(QMouseEvent *e) { if(e->button() == Qt::LeftButton){ ui->plainTextEdit->clear(); ui->label->show(); mythread = new ThreadLock(); connect(mythread, &ThreadLock::finished, this, &MainWindow::onThreadFinished); mythread->setLogic(SM_Thread::TYPR_WAR); mythread->start(QThread::LowPriority); gif->start(); } else{ } } void MainWindow::onThreadFinished() { SM_Thread type = mythread->from; switch (type) { case SM_Thread::TYPE_DEG: break; case SM_Thread::TYPE_RES: break; case SM_Thread::TYPE_INFO: break; case SM_Thread::TYPR_WAR: QList res = mythread->res; foreach(auto var, res) { ui->plainTextEdit->appendPlainText(var); //让主程序继续执行代码 QCoreApplication::processEvents(); } break; } ui->label->hide(); mythread->quit(); mythread->deleteLater(); mythread->wait(); } #include "threadlock.h" ThreadLock::ThreadLock() { } ThreadLock::~ThreadLock() { } void ThreadLock::setLogic(SM_Thread var) { from = var; } void ThreadLock::run() { switch(from){ case TYPE_INFO : //执行对应代码 //test(); break; case TYPE_DEG : //执行对应代码 //test(); break; case TYPE_RES : //执行对应代码 //test(); break; case TYPR_WAR : //执行对应代码 comIntensive(); break; } } void ThreadLock::comIntensive() { res.clear(); do{ double resInf = ((qrand() * 1.00)/(RAND_MAX * 10)) * 1000.00; QString resStr = QString::number(resInf,'f',2); if(!res.contains(resStr)){ Lock.tryLockForWrite(); res.append(resStr); Lock.unlock(); } else{ } } while(!res.isEmpty() && res.size() |
今日新闻 |
点击排行 |
|
推荐新闻 |
图片新闻 |
|
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭 |