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)的更多相关文章

  1. Qt 如何处理密集型耗时的事情(频繁调用QApplication::processEvents)

    有时候需要处理一些跟界面无关的但非常耗时的事情,这些事情跟界面在同一个线程中,由于时间太长,导致界面无法响应,处于“假死”状态.例如:在应用程序中保存文件到硬盘上,从开始保存直到文件保存完毕,程序不响 ...

  2. Qt 如何处理密集型耗时的事情

    有时候需要处理一些跟界面无关的但非常耗时的事情,这些事情跟界面在同一个线程中,由于时间太长,导致界面无法响应,处于“假死”状态.例如:在应用程序中保存文件到硬盘上,从开始保存直到文件保存完毕,程序不响 ...

  3. 使用ViewPager切换Fragment时,防止频繁调用OnCreatView

    使用ViewPager切换Fragment,我原先使用系统自带的适配器FragmentPagerAdapter. 切换fragment时,频繁调用oncreatview(). 查看FragmentPa ...

  4. mixare的measureText方法在频繁调用时抛出“referencetable overflow max 1024”的解决方式

    这几天在搞基于位置的AR应用,採用了github上两款开源项目: mixare android-argument-reality-framework 这两个项目实现机制大致同样.我选取的是androi ...

  5. javascript 函数节流 throttle 解决函数被频繁调用、浏览器卡顿的问题

    * 使用setTimeout index.html <html> <head> <meta charset="UTF-8"> <title ...

  6. Qt 如何处理拖放应用程序参数时,中国

    你用 Qt 我们开发的应用程序.用户拖放文件到您的 exe 在.启动应用程序,在这个时候, main() 功能参数可以接收中国.如何正确处理它?非常easy,码如下面: QTextCodec *cod ...

  7. Qt事件分发机制源码分析之QApplication对象构建过程

    我们在新建一个Qt GUI项目时,main函数里会生成类似下面的代码: int main(int argc, char *argv[]) { QApplication application(argc ...

  8. Qt技巧:QProcess与外部程序的调用

    项目做到一定阶段,常常须要在原来的project上调用外部程序. Qt为此提供了QProcess类,QProcess可用于完毕启动外部程序,并与之交互通信. 一.启动外部程序的两种方式: (1)一体式 ...

  9. Qt一步一步实现插件调用(附源码)

    最近手里几个项目都采用插件的方式进行开发工作,这里记录一下实现方法,给需要的同学一个参考, 在linux系统和window系统都能成功编译通过,不废话直接步骤 第一步:建立插件原型 新建一个Qt项目, ...

随机推荐

  1. SQL 客户端查看

    SELECT *FROM master.dbo.sysprocesses (nolock)ORDER BY hostname DESC

  2. js的cookie和sesession详解

    会话(Session)跟踪是Web程序中常用的技术,用来跟踪用户的整个会话.常用的会话跟踪技术是Cookie与Session.Cookie通过在客户端记录信息确定用户身份,Session通过在服务器端 ...

  3. Vue渲染列表,在更新data属性后,列表未更新问题

    初始化代码如下var tableModel = new Vue({el: '#datatable',data: {items: listData}}); 当我对列表操作时,listData=>n ...

  4. [tem]最长上升子序列

    Longest Increasing Subsequence(LIS) 一个美丽的名字 非常经典的线性结构dp [朴素]:O(n^2) d(i)=max{0,d(j) :j<i&& ...

  5. me 云面试

    元祖的特点: 1.元组内的元素,不可以增加,删除,只能访问,这个是元祖的特性,比较安全.类似于字符串.但是我们可以对整个元祖进行删除.使用del内置函数 2.当元祖内只有一个元素的时候,需要加逗号消除 ...

  6. Module not found: Error: Can't resolve 'XXX' in 'XXXX'

    故障 控制台运行webpack/npm时出现 Module not found: Error: Can't resolve 'XXX' in 'XXXX' 解决方案 npm i XXX --save ...

  7. [POJ1006]生理周期 (中国剩余定理)

    蒟蒻并不会中国剩余定理 交的时候还出现了PE的错误 下面是AC代码 #include<iostream> #include<cstdio> using namespace st ...

  8. Java 异常 重写抛出异常限制

    1 子类在重写父类抛出异常的方法时,要么不抛出异常,要么抛出与父类方法相同的异常或该异常的子类.如果被重写的父类方法只抛出受检异常,则子类重写的方法可以抛出非受检异常.例如,父类方法抛出了一个受检异常 ...

  9. margin塌陷

    我工作基本上就是写业务逻辑,不怎么写页面就一直觉得页面布局特高深.有天我同事问我,知道margin塌陷是什么东西不,我说我不知道(反正我也不用,管他呢),他说面试的时候问的(...那这必须得去看啊). ...

  10. JAVA中使用LOG4J记录日志(转)

    在项目开发中,记录错误日志是一个很有必要功能.一是方便调试:二是便于发现系统运行过程中的错误:三是存储业务数据,便于后期分析: 在java中,记录日志,有很多种方式. 比如,自己实现. 自己写类,将日 ...