QT

您所在的位置:网站首页 qtmovetothread发送信号出现线程对象收不到的情况 QT

QT

2024-07-08 12:45:01| 来源: 网络整理| 查看: 265

目录

        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()


【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭