织梦CMS - 轻松建站从此开始!

罗索

纠正你的Qt编程习惯:主窗体的创建问题

落鹤生 发布于 2011-10-20 10:58 点击:次 
要知道,并不是只有初学者才会犯错。(shiroki的至理名言)最近发现了一些有意思的问题,值得memo一下。
TAG:

题记: 要知道,并不是只有初学者才会犯错。(shiroki的至理名言)

最近发现了一些有意思的问题,值得memo一下。

先来看段代码:

  1. #include <QApplication> 
  2. #include <QWebView> 
  3. #include <QUrl> 
  4. int main(int argc, char* argv[]) 
  5.     QApplication a(argc, argv); 
  6.     QWebView* mw = new QWebView; 
  7.     mw->show(); 
  8.     mw->load(QUrl("http://www.cuteqt.com/blog")); 
  9.     return a.exec(); 

大家看得出这段代码中的问题吗? (呵呵,不要告诉我是cuteqt不能访问哦~)

这段代码ms十分标准, 非常符合笔者平时写Qt程序书写main函数的习惯, 孰料想竟然是个错误的习惯,而且问题很严重哦。 给个提示:在程序退出时会aborted。

如果还没想出来是什么问题,嘿嘿,没关系,看了下面的答案你就明白了。

在这段程序里 QApplication实例创建在stack上,生命期是main的大括号内, 而mw则通过new创建在heap上, 在程序退出时才会被析构。 换句话说,mw的生存期长于application的生存期…..这可是Qt编程的大忌, 因为在Qt中所有的Paint Device都必须要在有QApplication实例的情况下创建和使用。 不过如果把这个程序写出来运行一下, 未必会出现我说的aborted的问题,  大多数代码类似的程序都能安全的运行(这也是为什么用了那么多年的Qt从来没有注意过这个问题, 并且养成了我错误的编程习惯。)。  这里的trick在于application退出时mw已经被关闭, mw中的所有Paint Device一般都不会被访问到了, 所以这个错误隐藏在很深的阴暗角落, 偷偷地嘲笑我们呢!

要想试验这个问题也很简单,把load的参数换成本地文件 test.html, 并把下面的内容写进test.html就能看到拉:

  1. -----test.html----- 
  2. <form> 
  3. <select id="headertest"
  4. <option>Item1</option> 
  5. <option>Item2</option> 
  6. <option>Item3</option> 
  7. </select> 
  8. </form> 

这个html里使用了下拉选单。 如果你运行程序并点开该选单,之后退出程序你就会看到Aborted错误提示,并打印出错误信息:“QWidget: Must construct a QApplication before a QPaintDevice”。

既然提出的问题,当然也要给出解决的方案。 有两种可行的方法避免该错误。 一个当然是纠正一下编程习惯,对mw不要用new的方式创建,改在stack上创建,如下代码:

  1. #include <QApplication> 
  2. #include <QWebView> 
  3. #include <QUrl> 
  4. int main(int arg, char* argv[]) 
  5.     QApplication a(argc, argv); 
  6.     QWebView mw; 
  7.     mw.show(); 
  8.     mw.load(QUrl("http://www.cuteqt.com/blog")); 
  9.     return a.exec(); 

另外还可以用Qt提供的API解决此 问题, 想办法让mw在application之前clean up, 那就是用WA_DeleteOnClose属性。 该属性标示窗体会在close时被析构, 这样就保证不会留存在application析构之后了, 是个很好的办法。

代码如下:

  1. #include <QApplication> 
  2. #include <QWebView> 
  3. #include <QUrl> 
  4. int main(int arg, char* argv[]) 
  5.     QApplication a(argc, argv); 
  6.     QWebView* mw = new QWebView; 
  7.     mw->show(); 
  8.     mw->setAttribute(Qt::WA_DeleteOnClose); 
  9.     mw->load(QUrl("http://www.cuteqt.com/blog")); 
  10.     return a.exec(); 
(shiroki)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/201110/15168.html]
本文出处:blog.csdn.net 作者:shiroki
顶一下
(2)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容