QT简单入门实例7【解决界面阻塞问题】

界面卡死的原因:

1.密集计算

当你想在主线程创建类似 while(1)的这种死循环时,你可能会写下这样的代码:

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::on_pushButton_clicked()
{
    while(1)
        qDebug()<<"1";
}

当按钮槽函数被执行时,界面会被阻塞,确切的说是界面所在的主线程被占用,无法响应任何事件。
在这里插入图片描述

2. 调用阻塞

当你在主线程调用动态库或脚本时,比如你调用了一个python接口,但调用这个接口花费了一些时间。
直到调用过程返回,主线程都无法响应任何事件。即使这个时间很短(比如几十毫秒),也足以使你的界面响应卡顿,严重影响用户体验。

解决方法:

1.最简易的解决办法,但是效果不好

你可以在循环中加入这样一句话,编译器就会让CPU留出一部分时间用以响应事件。

    while(1){
        qApp->processEvents(); //开启事件循环
        qDebug()<<"1";
    }

你也可以这样做:要记得添加头文件 #include < QTime >
以非阻塞的方式延时10ms,本质也是调用了QCoreApplication::processEvents()

void MainWindow::on_pushButton_clicked()
{
    while(1){
        delayMSec(10); //延时10ms
        qDebug()<<"1";
    }
}
void MainWindow::delayMSec(unsigned int msec)
{
    QTime Time_set = QTime::currentTime().addMSecs(msec);
    while( QTime::currentTime() < Time_set )
        QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
}

但是一旦计算变得很密集,或者调用接口变得时间更长,这种方法就显得很无力了。

2.最彻底的解决办法,也是最专业的办法

  1. 当你要执行一个计算密集但不频繁的操作时,明智的办法是采用异步计算来实现。可以借助 QtConcurrent,QFuture,QFutureWatcher 将函数放在子线程进行异步计算。
  2. 当你要执行一个频繁的UI无关操作时,可以使用QThread 来开启一个长期运行的子线程,但是要警惕多线程的冲突与死锁。还有,最好使用 QObject::moveToThread(QThread* thread) 方法,而不是重写QThread 类的虚函数run() 来实现。线程间若采用信号槽进行通信,要注意其连接方式。

这两种方法具体请参照我后面的博文,我会以最简单直接的方式进行说明。

  • 6
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值