首页 > 其他分享 >Qt执行耗时操作导致界面卡顿的三种解决办法

Qt执行耗时操作导致界面卡顿的三种解决办法

时间:2022-11-01 18:00:48浏览次数:44  
标签:run Qt int QtConcurrent 耗时 界面 SmartApartPlayThread 卡顿

1.问题描述

Qt界面程序开发中,会遇到执行耗时操作时,导致界面卡顿。原因是界面主线程是单线程,如果在UI主线程中执行耗时操作,例如点击按钮,响应函数去数据库查询数据,数据量比较大时,查询需要几秒钟甚至几十秒的时间,如果UI主线程一直等待响应函数返回,阻塞在响应函数内部,就无法响应界面的其他消息或者事件,界面就会卡死,无响应;

 

2.解决方法

2.1用Qt::QueuedConnection去连接信号槽

Qt::QueuedConnection是用队列的形式执行操作,点击pushButtonStart按钮之后,会立刻返回,不用等到startSmartApart();执行完成再返回;startSmartApart();5秒内执行完,可以考虑这种方法,超过5秒,界面也会卡顿;

connect(ui.pushButtonStart, &QPushButton::clicked, this, [=]() {
		//QtConcurrent::run(this, &test::startSmartApart);
		startSmartApart();
	},Qt::QueuedConnection);

2.2用QtConcurrent::run将类函数放入线程中执行;

(1)QtConcurrent::run会创建一个新的线程,将类函数放入新的线程中执行;也可以返回返回值;

connect(ui.pushButtonStart, &QPushButton::clicked, this, [=]() {
        QtConcurrent::run(this, &test::startSmartApart);
        //startSmartApart();
    },Qt::QueuedConnection);

(2)可以给执行的类函数startSmartApartCount(int count)传入多个参数,最多5个参数;

connect(ui.pushButtonStart, &QPushButton::clicked, this, [=]() {
        //QtConcurrent::run(this, &test::startSmartApart);
        int retval = -1;
        QtConcurrent::run(this, &test::startSmartApartCount,100);
        //startSmartApart();
    },Qt::QueuedConnection);

(3)同步方法获取函数的返回值,但是 future.waitForFinished();会阻塞主线程等待结果返回,导致界面卡死;

connect(ui.pushButtonStart, &QPushButton::clicked, this, [=]() { 
        int retval = -1;
        QFuture<int> future = QtConcurrent::run(this, &test::startSmartApartCount, 10);
        future.waitForFinished();//阻塞等待结果返回
        qDebug() << future.result();
    },Qt::QueuedConnection);

(4)异步方法获取函数返回值,使用QFutureWatcher信号槽监视返回结果,不阻塞主线程,界面很流畅

//类的成员变量

QFuture<int> future;

QFutureWatcher<int>* watcher;

watcher = new QFutureWatcher<int>();
    connect(ui.pushButtonStart, &QPushButton::clicked, this, [=]() {
         future = QtConcurrent::run(this, &test::startSmartApartCount, 2);
        
        QObject::connect(watcher, &QFutureWatcher<int>::finished,this, [&]() {
            qDebug() << future.result();
        });
        watcher->setFuture(future);
    },Qt::QueuedConnection);

2.3用QThread执行耗时操作

(1)创建线程类

头文件

#ifndef SmartApartPlayThread_H
#define SmartApartPlayThread_H

#include <QThread>
class SmartApartPlayThread : public QThread
{
    Q_OBJECT

public:
    SmartApartPlayThread();
    ~SmartApartPlayThread();
    int StartSmartApartPlay(void* pmulti,int index);
    void run();
signals:
    void signalStartApartPlay(int index);

private:
    void* m_pmulti=nullptr;
    int m_index=0;
};

#endif // COPYFILETHREAD_H

 

源文件

#include "SmartApartPlayThread.h"
#include <windows.h>
SmartApartPlayThread::SmartApartPlayThread()
{

}

SmartApartPlayThread::~SmartApartPlayThread()
{

}

int SmartApartPlayThread::StartSmartApartPlay(void* pmulti, int index)
{
    m_pmulti = pmulti;
    m_index = index;
    if (m_pmulti!=nullptr)
    {
        start();
    }
    return 0;
}



void SmartApartPlayThread::run()
{
    
    while (1)
    {
        Sleep(10000);
    }
}

(2)按钮响应函数中启动线程执行耗时操作

connect(ui.pushButtonStart, &QPushButton::clicked, this, [=]() {
        m_SmartApartPlayThread.StartSmartApartPlay(this,10);
    },Qt::QueuedConnection);
    

 

3.总结

要实现好的用户体验,实现流程的界面操作程序,就不能老是卡,比较好的方式就是采用异步操作、多线程等方法来实现异步,并发;这样才会有好的交互体验;QtConcurrent::run和线程其实原理上都是多线程并发方式,只是QtConcurrent::run封装了线程的操作;可以执行类函数,更方便一些;

 

标签:run,Qt,int,QtConcurrent,耗时,界面,SmartApartPlayThread,卡顿
From: https://www.cnblogs.com/bclshuai/p/16359896.html

相关文章

  • 怎么结束线程不崩溃不卡顿
    1.问题描述Qt开发客户端程序时,因为耗时的数据库查询操作会阻塞主界面线程,所以把耗时操作放入新建的子线程中去执行,用过子线程的信号和主线程的槽函数连接,返回查询结果;这样......
  • Qt编写本地摄像头综合应用示例(qcamera/ffmpeg/v4l2等)
    一、功能特点同时支持qcamera、ffmpeg、v4l2三种内核解析本地摄像头。提供函数findCamera自动搜索环境中的所有本地摄像头设备,搜索结果信号发出。支持自动搜索和指......
  • 【QT】创建动态链接库及使用
    创建动态链接库创建一个项目选择library的C++库,下一步。选择共享库,输入动态库的名字,选择创建路径,下一步选择编译环境,下一步选择QTCore模块,该模块提供核心的非图......
  • Qt+VLC简单的使用显示视频Demo
    先看看效果: vlc播放视频,要比QMediaPlayer实用的多,并且同时运行20个视频时不会出现卡顿。 这个Demo功能实现非常简单,简单的说一下vlc流程:1、创建并初始化一个libvlc实例LI......
  • Qt检测U盘插入拔出Demo
    要做这个,要先知道Qt的QAbstractNativeEventFilter类,虚函数nativeEventFilter。这个类的主要作用是捕获全局windows消息。先看一下效果:基本注意以下两点:1、新建的类要继承QAb......
  • Qt5.6作浏览器Demo可查看地图
    这里用到了ui提升部件的小方法,记得设置控件为Microsoft webbrowser,先看看效果:用到ui里面的QAxWidget控件,用以下这个类来提升这个控件。#include<ActiveQt/QAxWidget>#inc......
  • Qt用Poppler库解析PDF成图片的简单示例
    解析PDF这里用的是Poppler库,与之相关的库还有MuPDF库,参考了这个链接:​​https://people.freedesktop.org/~aacid/docs/qt5/​​相关链接:​​qt显示pdf——poppler-qt问题​......
  • Qt对Json的生成与解析Demo
    QJsonObject类用于封装JSON对象。JSON对象是键值对,其中键是唯一的字符串,其值由QJsonValue代表。一个QJsonObject可以从QVariantMap转换/被转换。QJsonArray类用于封装JSON数......
  • Qt创建和删除文件小Demo(顺便讲了补全功能)
    背景:笔者需要创建和删除多个pdd和多个pff文件(这些是自己创建的类型),一个个手动创建和删除很麻烦,就做了一款小软件解决此问题。先看一下效果:代码如下:①、头文件:#ifndefMAINWI......
  • Qt的正则表达式
     如果使用的是QtQuick的正则表达式,请读我以前的博客首先明白什么是正则表达式:正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,......