[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项目, ...
随机推荐
- BZOJ.4821.[SDOI2017]相关分析(线段树)
BZOJ LOJ 洛谷 恶心的拆式子..然后就是要维护\(\sum x_i,\ \sum y_i,\ \sum x_iy_i,\ \sum x_i^2\). 操作三可以看成初始化一遍,然后同操作二. ...
- 洛谷 P1078 文化之旅(CODEVS 1316)
题目描述 有一位使者要游历各国,他每到一个国家,都能学到一种文化,但他不愿意学习任何一 种文化超过一次(即如果他学习了某种文化,则他就不能到达其他有这种文化的国家).不 同的国家可能有相同的文化.不同 ...
- java中打开文件流后要关闭后重新打开
记录错误,打开文件流一定要关闭并重新打开文件流,不然取的文件内容永远是第一次取的文件内容: /** * 读取配置文件 */ private Properties readProperties() { ...
- C#中Key事件
在键盘按下键然后释放的过程中有3个事件发生,分别为KeyDown事件.KeyPress事件和KeyUp事件. KeyDown和KeyUp事件让应用程序捕捉用户在键盘上按下的特殊键或某些特定键甚至组合键 ...
- Math.round()
在 JAVA 中四舍五入采用 Math.round(T a) 函数,函数返回的是一个 long 类型的长整型,参数 a 可以是 double 也可以是 float. 查看 JDK 源码: public ...
- Wooden Sticks [POJ1065] [DP]
Description 有N根木棍等待处理.机器在处理第一根木棍时需要准备1分钟,此后遇到长宽都不大于前一根木棍的木棍就不需要时间准备,反之则需要1分钟重新准备.比如木棍按照(3,3).(1,3).( ...
- Flask jinja2
{{ }} #引用 执行 非逻辑代码 {% %} #逻辑代码 引用变量 @app.template_global() # 全局函数 Markup # 安全标签字符串儿 {% macro func() ...
- redis:aof恢复与rdb服务器间迁移
1. aof恢复与rdb服务器间迁移: 1.1. Aof恢复: 如果不小心执行了flushdb或flushall了怎么办? (1)立马执行命令:shutdown nosave 关闭服务器,为了防止其他 ...
- 下拉框 tree 基于 EasyUi
public string DataTableToJson() { string dataJson = ""; string temp = ""; string ...
- django中数据库操作有关部分
# >>>>>>>>>>>>>>>>>>>>>>>>&g ...