[C++]Qt 如何处理密集型耗时的事情(频繁调用QApplication::processEvents)
https://www.cnblogs.com/senior-engineer/p/5598133.html
https://www.cnblogs.com/findumars/p/5607683.html
api含义:QCoreApplication::processEvents() 将处理所有事件队列中的事件并返回给调用者。
问题描述:
当主线程在某个槽函数里正在执行processEvents时, 刚好有一个能响应此槽函数的信号发送过来了(肯定是其他线程发的信号), 这时就可能会发生可怕的递归,
导致栈溢出崩溃。 原因是processEvents,进入到无尽的递归中。
示例代码:
bugThread.h
#include <QThread>
class BugThread : public QThread
{
Q_OBJECT
public:
BugThread(QObject* parent) : QThread(parent) {}
signals:
void sigBugsignal();
public:
void run()
{
while(true)
{
emit sigBugsignal();
}
}
};
bugs.h & bugs.cpp
class Bugs : public QMainWindow
{
Q_OBJECT public:
Bugs(QWidget *parent = 0, Qt::WFlags flags = 0);
~Bugs();
public slots:
void onBugSlot();
private:
Ui::BugsClass ui;
}; Bugs::Bugs(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
BugThread* bt = new BugThread(this);
connect(bt, SIGNAL(sigBugsignal()), this, SLOT(onBugSlot()));
bt->start();
} Bugs::~Bugs()
{ }
void Bugs::onBugSlot()
{
Sleep(1);
QApplication::processEvents();
}
===========================================================================================
有时候需要处理一些跟界面无关的但非常耗时的事情,这些事情跟界面在同一个线程中,由于时间太长,导致界面无法响应,处于“假死”状态。例如:在应用程序中保存文件到硬盘上,从开始保存直到文件保存完毕,程序不响应用户的任何操作,窗口也不会重新绘制,从而处于“无法响应”状态,这是一个非常糟糕的体验 。
在这种情况下,有一种方法是使用多线程,即在子线程中处理文件保存,主线程负责界面相关。
而如果不想使用多线程,最简单的办法就是在文件保存过程中频繁调用QApplication::processEvents()。该函数的作用是让程序处理那些还没有处理的事件,然后再把使用权返回给调用者。
代码如下:


bool MyApp::writeFile(const QString &filename)
{
QFile file(filename);
...
QApplication::setOverrideCursor(Qt::WaitCursor);
for(int r = 0; r != rowCount; ++r)
{
for(int c = 0; c != colCount; ++c)
{
out << table(r,c);
qApp.processEvents();
}
}
QApplication::restoreOverrideCursor();
}


这样一来,程序就能响应了。
但是,该方法有一个问题:可能正在保存文件的过程中,用户不小心又单击了保存,或不小心关闭了程序主窗口,这样会产生意想不到的后果。
解决这个问题的最简单的办法是替换成:
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);//它可以忽略用户的输入(鼠标和键盘事件)。
进一步的,如果想显示一个带有进度条的对话框,随时显示当前的进度状态,可以使用QProgressDialog。


bool MyApp::writeFile(const QString &filename)
{
QFile file(filename);
...
QApplication::setOverrideCursor(Qt::WaitCursor);
QProgressDialog progress;
progress.setWindowTitle(tableData->sNameCH);
progress.setLabelText(QStringLiteral("数据保存中,请稍候..."));
//progress.setCancelButton(0);//不显示“取消”按钮
progress.setCancelButtonText("取消");
progress.setRange(0,rowCount );
progress.setModal(true);
//此处没有调用show()来显示,是因为QProgressDialog会自动决定是否显示
//如果时间过短,就不会显示。
for(int r = 0; r != rowCount; ++r)
{
progress.setValue(row);
//如果用户单击了“取消”,就取消保存文件,并删除该文件。
if(progress.wasCanceled)
{
file.remov();
return false;
}
for(int c = 0; c != colCount; ++c)
{
out << table(r,c);
qApp.processEvents();
}
}
QApplication::restoreOverrideCursor();
}
[C++]Qt 如何处理密集型耗时的事情(频繁调用QApplication::processEvents)的更多相关文章
- Qt 如何处理密集型耗时的事情(频繁调用QApplication::processEvents)
有时候需要处理一些跟界面无关的但非常耗时的事情,这些事情跟界面在同一个线程中,由于时间太长,导致界面无法响应,处于“假死”状态.例如:在应用程序中保存文件到硬盘上,从开始保存直到文件保存完毕,程序不响 ...
- Qt 如何处理密集型耗时的事情
有时候需要处理一些跟界面无关的但非常耗时的事情,这些事情跟界面在同一个线程中,由于时间太长,导致界面无法响应,处于“假死”状态.例如:在应用程序中保存文件到硬盘上,从开始保存直到文件保存完毕,程序不响 ...
- 使用ViewPager切换Fragment时,防止频繁调用OnCreatView
使用ViewPager切换Fragment,我原先使用系统自带的适配器FragmentPagerAdapter. 切换fragment时,频繁调用oncreatview(). 查看FragmentPa ...
- mixare的measureText方法在频繁调用时抛出“referencetable overflow max 1024”的解决方式
这几天在搞基于位置的AR应用,採用了github上两款开源项目: mixare android-argument-reality-framework 这两个项目实现机制大致同样.我选取的是androi ...
- javascript 函数节流 throttle 解决函数被频繁调用、浏览器卡顿的问题
* 使用setTimeout index.html <html> <head> <meta charset="UTF-8"> <title ...
- Qt 如何处理拖放应用程序参数时,中国
你用 Qt 我们开发的应用程序.用户拖放文件到您的 exe 在.启动应用程序,在这个时候, main() 功能参数可以接收中国.如何正确处理它?非常easy,码如下面: QTextCodec *cod ...
- Qt事件分发机制源码分析之QApplication对象构建过程
我们在新建一个Qt GUI项目时,main函数里会生成类似下面的代码: int main(int argc, char *argv[]) { QApplication application(argc ...
- Qt技巧:QProcess与外部程序的调用
项目做到一定阶段,常常须要在原来的project上调用外部程序. Qt为此提供了QProcess类,QProcess可用于完毕启动外部程序,并与之交互通信. 一.启动外部程序的两种方式: (1)一体式 ...
- Qt一步一步实现插件调用(附源码)
最近手里几个项目都采用插件的方式进行开发工作,这里记录一下实现方法,给需要的同学一个参考, 在linux系统和window系统都能成功编译通过,不废话直接步骤 第一步:建立插件原型 新建一个Qt项目, ...
随机推荐
- 【持久化框架】Mybatis与Hibernate的详细对比(转发)
前言 这篇博文我们重点分析一下Mybatis与Hibernate的区别,当然在前面的博文中我们已经深入的研究了Mybatis和Hibernate的原理. Mybatis [持久化框架]Mybatis简 ...
- Scrapy基础(八)————图片下载后将本地路径添加到Item中
前边讲到简单的图片下载,但是怎样将图片的本地路径和存储在Item中的数据对应起来,所以本篇博文讲解到如何将 本地的下载后的图片路径写入到Item中 思路:自定义pipline,多加个管道,该管道继承下 ...
- Ajax状态值及状态码整理
1- AJAX状态值与状态码区别 AJAX状态值是指,运行AJAX所经历过的几种状态,无论访问是否成功都将响应的步骤,可以理解成为AJAX运行步骤.如:正在发送,正在响应等,由AJAX对象与服务器交互 ...
- 潭州课堂25班:Ph201805201 django 项目 第四十一课 后台 轮播图管理功能讲解,文档管理功能 实现 (课堂笔记)
在进入轮播图管理页面时,要把轮播图显示在页面上,所以后台要向前台返回: 图片路由,:image_url 优先级: priority def get(self, request): # priority ...
- 让大疆去做测绘---航线规划软件APP
让大疆去做测绘---航线规划软件APP http://blog.zhulong.com/u10783270/blogdetail7162540.html RockyCapture无人机航线飞行控制软件 ...
- 多轴APM飞控调参
调参步骤: 遥控器,电动机和电调对应的APM飞控连线——遥控器校准——电调行程校准——加速度计校准——磁罗盘校准——故障保护设定(遥控器和飞控)——飞行模式设定并调整——自动调参设定选项 APM飞控调 ...
- vue的生存周期
钩子函数 created 实例已经创建 befoCompile 编译之前 compiled 编译之后 ready 插入到文档 beforeDestroy 销毁之前 destroyed 销毁之后
- [模板][P4238]多项式求逆
NTT多项式求逆模板,详见代码 #include <map> #include <set> #include <stack> #include <cmath& ...
- mysql存储过程相关记录
一个标准的存储过程创建语句 CREATE PROCEDURE myTestPro ( ), OUT rtv ) ) BEGIN SET rtv = text; END; 这个存储过程有一个输入参数以及 ...
- 编程菜鸟的日记-初学尝试编程-编写函数实现strlen功能(总结考察点)
//考察点1:输入参数加const int Mystrlen(const char *str) {//考察点2:断言字符串非0 assert(str!=NULL); int len=0;//考察点3: ...