- 浏览: 3454586 次
- 性别:
- 来自: 苏州
-
文章分类
最新评论
-
sonichy:
Qt5改动很多,要改改了。
基于QItemDelegate的例子1 SpinBoxDelegate -
我的主页6:
楼主,2.2子查询的分页方式:SELECT * FROM ar ...
Mysql 分页语句Limit用法 -
liguoqi:
非常感谢楼主的用心指导,工具以及图片例子都提供了 赞!
两款免费DCIOM 图像浏览软件介绍和DICOM图像例子供下载 -
liguoqi:
问下这个图片怎么解压损坏呀
两款免费DCIOM 图像浏览软件介绍和DICOM图像例子供下载 -
liguoqi:
楼主讲解的非常详细,还附带工具和图片例子,非常感谢
两款免费DCIOM 图像浏览软件介绍和DICOM图像例子供下载
转载:http://blog.csdn.net/dbzhang800/article/details/6889291
- 本文旨在说明:QDialog::exec()、QMenu::exec()等开启的局部事件循环,易用的背后,还有很多的陷阱...
引子
Qt 是事件驱动的,基本上,每一个Qt程序我们都会通过QCoreApplication或其派生类的exec()函数来开启事件循环(QEventLoop):
int main(int argc, char**argv) { QApplication a(argc, argv); return a.exec(); }
但是在同一个线程内,我们可以开启多个事件循环,比如通过:
- QDialog::exec()
- QDrag::exec()
- QMenu::exec()
- ...
这些东西都很常用,不是么?它们每一个里面都在执行这样的语句:
QEventLoop loop; //事件循环 loop.exec();
既然是同一线程内,这些显然是无法并行运行的,那么只能是嵌套运行。
如何演示?
如何用最小的例子来直观说明这个问题呢?
利用定时器来演示应该是最方便的。于是,很容易写出来这样的代码:
#include <QtCore> class Object : public QObject { public: Object() {startTimer(200); } protected: void timerEvent(QTimerEvent *) { static int level = 0; qDebug()<<"Enter: <<"++level; QEventLoop loop; //事件循环 loop.exec(); qDebug()<<"Leave: "<<level; } }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Object w; return a.exec(); }
然后我们可以期待看到:
Enter: 1 Enter: 2 Enter: 3 ...
但是,很让人失望,这并不会工作。因为Qt对Timer事件派发时进行了处理:
- 如果当前在处理Timer事件,新的Timer将不会被派发。
演示
我们对这个例子进行一点改进:
- 收到Timer事件后,我们立即post一个自定义事件(然后我们在对自定义事件的相应中开启局部的事件循环)。这样Timer事件的相应可以立即返回,新的Timer事件可以持续被派发。
另外,为了友好一点,使用了 QPlainTextEdit 来显示结果:
#include <QtGui> #include <QtCore> class Widget : public QPlainTextEdit { public: Widget() {startTimer(200); } protected: bool event(QEvent * evt) { if (evt->type() == QEvent::Timer) { qApp->postEvent(this, new QEvent(QEvent::User)); } else if (evt->type() == QEvent::User) { static int level = 0; level++; this->appendPlainText(QString("Enter : %1").arg(++level)); QEventLoop loop; loop.exec(); this->appendPlainText(QString("Leave: %1").arg(level)); } return QPlainTextEdit::event(evt); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
有什么用?
这个例子确实没有什么,因为似乎没人会写这样的代码。
但是,当你调用
- QDialog::exec()
- QMenu::exec()
- QDrag::exec()
- ...
等函数时,实际上就启动了嵌套的事件循环,而如果不小心的话,还有遇到各种怪异的问题!
== QDialog::exec() vs QDialog::open()== 在 QDialog 模态对话框与事件循环 以及 漫谈QWidget及其派生类(四) 我们解释过QDialog::exec()。它最终就是调用QEventLoop::exec()。
QDialog::exec()这个东西是这么常用,以至于我们很少考虑这个东西的不利因素。QDialog::open()尽管被官方所推荐,但是似乎很少有人用,很多人可能还不知道它的存在。
但是Qt官方blog中:
一文介绍了 exec() 可能造成的危害,并鼓励大家使用 QDialog::open()
在Qt官方的Qt Quarterly中: * QtQuarterly30 之 New Ways of Using Dialogs 对QDialog::open()有详细的介绍
QDialog::open()劣势与优势
看个例子:我们通过颜色对话框选择一个颜色,
- 使用静态函数,写法很简介(内部调用exec()启动事件循环)
void Widget::onXXXClicked() { QColor c = QColorDialog::getColor(); }
- 对话框的常见用法,使用exec()启动事件循环,很直观
void Widget::onXXXClicked() { QColorDialog dlg(this); dlg.exec(); QColor c = dlg.currentColor(); }
- 使用open()函数,比较不直观(因为是异步,需要链接一个槽)
void Widget::onXXXClicked() { QColorDialog *dialog = new QColorDialog; dialog->open(this, SLOT(dialogClosed(QColor))); } void Widget::dialogClosed(const QColor &color) { QColor = color; }
好处嘛(就摘录Andreas Aardal Hanssen的话吧):
- By using open() instead of exec(), you need to write a few more lines of code (implementing the target slot). But what you gain is very significant: complete control over execution. Now, the event loop is no longer nested/reentered, you’re not blocking inside a magic exec() function
局部事件循环导致崩溃
Kde开发者官方blog中描述这个问题:
在某个槽函数中,我们通过QDialog::exec() 弹出一个对话框。
void ParentWidget::slotDoSomething() { SomeDialog dlg( this ); //分配在栈上的对话框 if (dlg.exec() == QDialog::Accepted ) { const QString str = dlg.someUserInput(); //do something with with str } }
如果这时ParentWidget或者通过其他方式(比如dbus)得到通知,需要被关闭。会怎么样?
程序将崩溃:ParentWidget析构时,将会delete这个对话框,而这个对话框却在栈上。
简单模拟一下(在上面代码中加一句即可):
void ParentWidget::slotDoSomething() { QTimer::singleShot(1000, this, SLOT(deleteLater())); ...
这篇blog最终给出的结论是:将对话框分配到堆上,并使用QPointer来保存对话框指针。
上面的代码,大概要写成这样:
void ParentWidget::slotDoSomething() { QWeakPointer<SomeDialog> dlg = new SomeDialog(this); if (dlg.data()->exec() == QDialog::Accepted ) { const QString str = dlg.data()->someUserInput(); //do something with with str } else if(!dlg) { //.... } if (!dlg) { delete dlg.data(); } }
感兴趣的可以去看看原文。比较起来 QDialog::open() 应该更值得考虑。
QCoreApplication::sendPostedEvents()
当程序做繁重的操作时,而又不愿意开启一个新线程时,我们都会选择调用
QCoreApplication::sendPostedEvents ()
来使得程序保持相应。这和前面提到的哪些exec()开启局部事件循环的效果其实是完全一样的。
无论是这个,还是QEventLoop::exec()最终都是调用:
QAbstractEventDispatcher::processEvents()
来进行事件派发。前面的问题也都是由它派发的事件引起的。
参考
发表评论
-
Qt官网变更【2012】
2012-09-21 19:30 4231Qt最近被Digia完全收购,诺基亚这两年的不理不睬,没有魄力 ... -
【转】QT实现不规则窗体
2012-09-21 18:50 5028看到好文章,收藏一下: 看到网上有很多不规则窗体的实现 ... -
Qt应用程序如何使用DCMTK类库进行二次开发DICOM数据传输
2012-09-13 09:35 0参考文章: 1、Using DCMTK with ... -
【转】将QT开发的界面程序封装成DLL,在VC中成功调用
2012-09-11 10:33 21178最近手头的一个项目需要做一个QT界面,并且封装成DLL,然后 ... -
诺基亚挥别Qt,转手给Digia
2012-09-11 09:37 2877一家总部位于芬兰的IT业务供应商Digia今天宣布,已经签署了 ... -
Qt多线程间信号槽传递非QObject类型对象的参数
2012-09-07 15:29 21454一、以前就发现过这个问题: 在Qt项目中,有时候为了 ... -
QT样式表(QStyleSheet)
2012-08-17 10:37 17930QT样式表 (QStyleSheet) 作者:刘旭晖 ... -
FinalData磁盘文件恢复工具(绿色破解版)
2012-08-02 13:28 8645FinalData磁盘文件恢复工具(绿色破解版),使用起来很方 ... -
Eclipse Qt开发环境的建立【转】
2012-08-01 11:15 44211.下载Eclipse目前Eclipse+CDT已经可以 ... -
汽车辐射监测系统-Qt开发
2012-07-25 16:18 4711最近晚上抽空忙了两个月,才把一个小系统做完。虽然做的不是太完 ... -
Qt做发布版,解决声音和图片、中文字体乱码问题
2012-07-14 16:02 4884Qt做发布版,解决声音和图片、中文字体乱码问题 ... -
QTableView使用中的疑问,如何及时显示操作Model后的结果?
2012-06-01 14:52 0最终的解决方法:我正 ... -
【转】Qt QTableview使用
2012-06-01 09:49 9694QTableWidget是QT程序中常用的显示数 ... -
QTableView双击 单机事件信号
2012-06-01 09:47 23183双击QTableView的行,获取该行数据 代码 ... -
QMessageBox改变大小
2012-05-31 15:33 8489创建一个QMessageBox: QMessageBo ... -
更新QTableView中的进度条状态
2012-05-30 14:37 14916前段时间,我接触了,如何在一个QTableView中加入一个控 ... -
QThread 线程暂停 停止功能的实现
2012-05-29 11:56 12243为了实现Qt中线程的暂停运行,和停止运行的控制功能 需要在设 ... -
QT环境变量
2012-05-28 18:53 5604不知道为啥同事有台电脑,装完Qt-VS2008库,和VS Ad ... -
广告光
2012-05-24 18:33 0盈创广告联盟 http://www.yo114.cn/ ... -
Test
2012-05-24 18:22 2199Test<IMG SRC="cf08e32c2 ...
相关推荐
MTPA数值求解:双法探究,MTPA数值求解详解:两种方法的比较与应用探索,MTPA数值求解两种方法 ,MTPA数值求解; 方法一; 方法二;,MTPA数值求解的两种高效方法
# 踏入C语言的奇妙编程世界 在编程的广阔宇宙中,C语言宛如一颗璀璨恒星,以其独特魅力与强大功能,始终占据着不可替代的地位。无论你是编程小白,还是有一定基础想进一步提升的开发者,C语言都值得深入探索。 C语言的高效性与可移植性令人瞩目。它能直接操控硬件,执行速度快,是系统软件、嵌入式开发的首选。同时,代码可在不同操作系统和硬件平台间轻松移植,极大节省开发成本。 学习C语言,能让你深入理解计算机底层原理,培养逻辑思维和问题解决能力。掌握C语言后,再学习其他编程语言也会事半功倍。 现在,让我们一起开启C语言学习之旅。这里有丰富教程、实用案例、详细代码解析,助你逐步掌握C语言核心知识和编程技巧。别再犹豫,加入我们,在C语言的海洋中尽情遨游,挖掘无限可能,为未来的编程之路打下坚实基础!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
'Function 生成视频缩略图(ByVal 视频文件 As String, ByVal 保存缩略图的文件路径 As String, Optional ByVal jpg图像品质 As Long = 80, _ ' Optional ByVal 缩略图宽度 As Long = 500, Optional ByVal 缩略图高度 As Long = 500 _ ' , Optional 返回图像实际宽度 As Long, Optional 返回图像实际高度 As Long) As Boolean Public Function SaveImageAs(LoadImgFile As String, ByVal SaveAsImgFile As String, _ Optional ByVal JpgQuality As Long = 80, Optional hPal As Long, Optional Resolution As Single) As Boolean
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
bkall_answers(2).json
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
近日,一份由清华大学团队发布《DeepSeek:从入门到精通》的AI学习教程冲上了热搜,它是由清华大学新闻与传播学院新媒体研究中心元宇宙文化实验室的余梦珑博士后及其团队倾力打造,从三个方面深入剖析了DeepSeek,DeepSeek是什么?有什么用?怎么使用? 详细论述了其应用场景与使用方法,并讲解了如何通过设计精妙的提示语来提升AI的使用效率,以及丰富的实例干货。 全部104页,完整版资料已经帮大家整理好了,免费领取 资料链接: https://pan.quark.cn/s/be3b500c539c
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
冰点下载器珍藏版.zip
Wallpaper Engine 是一款广受欢迎的动态壁纸软件,允许用户将各种动态、交互式壁纸应用到桌面上。其丰富的创意工坊内容让用户可以轻松下载和分享个性化的壁纸。而“一键提取”功能则是 Wallpaper Engine 中一个非常实用的工具,能够帮助用户快速提取和保存壁纸资源,方便后续使用或分享。
科研人员
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
13考试真题最近的t66.txt
对外承包项目借款合同2[示范文本].doc
在日常的工作和学习中,你是否常常为处理复杂的数据、生成高质量的文本或者进行精准的图像识别而烦恼?DeepSeek 或许就是你一直在寻找的解决方案!它以其高效、智能的特点,在各个行业都展现出了巨大的应用价值。然而,想要充分发挥 DeepSeek 的优势,掌握从入门到精通的知识和技能至关重要。本文将从实际应用的角度出发,为你详细介绍 DeepSeek 的基本原理、操作方法以及高级技巧。通过系统的学习,你将能够轻松地运用 DeepSeek 解决实际问题,提升工作效率和质量,让自己在职场和学术领域脱颖而出。现在,就让我们一起开启这场实用又高效的学习之旅吧!
借助java编程语言和MySQL数据库等实现系统的全部功能,接下来对系统进行测试,测试系统是否有漏洞和测试用户权限来完善系统,最终系统完成达到相关标准。 本系统主要包括管理员和用户两个角色;主要包括首页、个人中心、用户管理、商品分类管理、商品信息管理、促销产品管理、系统管理、订单管理等功能的管理系统。 系统权限按管理员和用户这两类涉及用户划分。 (1)管理员功能需求 管理员登陆后,主要包括首页、个人中心、用户管理、商品分类管理、商品信息管理、促销产品管理、系统管理、订单管理等功能。 2)用户功能需求 用户登陆后进入小程序首页,可以实现首页、商品信息、促销产品、购物车、我的等,在我的页面可以对个人中心、我的收藏管理、用户充值、购物车、我的订单等功能进行详细操作。