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

标签: Qt技术 debug Qt | 发表时间:2009-12-16 10:06 | 作者:shiroki 三十不归
出处:http://www.cuteqt.com/blog

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

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

先来看段代码:

#include <QApplication>
#include <QWebView>
#include <QUrl>
int main(int argc, char* argv[])
{
    QApplication a(argc, argv);
    QWebView* mw = new QWebView;
    mw->show();
    mw->load(QUrl("http://www.cuteqt.com/blog"));
    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就能看到拉:


-----test.html-----
<form>
<select id="headertest">
<option>Item1</option>
<option>Item2</option>
<option>Item3</option>
</select>
</form>

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

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

#include <QApplication>
#include <QWebView>
#include <QUrl>
int main(int arg, char* argv[])
{
    QApplication a(argc, argv);
    QWebView mw;
    mw.show();
    mw.load(QUrl("http://www.cuteqt.com/blog"));
    return a.exec();
}

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

代码如下:

#include <QApplication>
#include <QWebView>
#include <QUrl>
int main(int arg, char* argv[])
{
    QApplication a(argc, argv);
    QWebView* mw = new QWebView;
    mw->show();
    mw->setAttribute(Qt::WA_DeleteOnClose);
    mw->load(QUrl("http://www.cuteqt.com/blog"));
    return a.exec();
}
发现问题和解决问题是件很有乐趣的事情,大家不要把时间都浪费在猜测上,要多动手多思考才能进步!

相关 [qt 编程 习惯] 推荐:

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

- 三十不归 - CuteQt Blog
题记: 要知道,并不是只有初学者才会犯错. 最近发现了一些有意思的问题,值得memo一下. 大家看得出这段代码中的问题吗. (呵呵,不要告诉我是cuteqt不能访问哦~). 这段代码ms十分标准, 非常符合笔者平时写Qt程序书写main函数的习惯, 孰料想竟然是个错误的习惯,而且问题很严重哦. 给个提示:在程序退出时会aborted.

Qt Project 上线

- ArmadilloCommander - LinuxTOY
还记得本站先前报道的 Qt 移至开放式管理么. 现在它的 Qt Project 网站正式上线了. 在发布报道中,为了表示 Qt 不再是 Nokia 的一言堂,特别指出了 QtCore 的维护者 Thiago 不是 Nokia 的雇员. Qt Project 主页. 收藏到 del.icio.us |.

Qt——转战Java?

- - 博客 - 伯乐在线
编者按:事实上,在跨平台开发方面,Qt仍是最好的工具之一,无可厚非,但Qt目前没有得到任何主流移动操作系统的正式支持. 诺基亚的未来计划,定位非常模糊,这也是令很多第三方开发者感到失望,因此将导致诺基亚屡遭失败的原因. Qt的主要开发者之一Mirko Boehm在博客上强烈讽刺Nokia裁了Qt部门的决定,称其为“绝望之举”,而非“策略变更”.

Qt ——塞班之死

- - 博客 - 伯乐在线
编者按:显然,关注Qt及nokia生死存亡的开发者还是大有人在,面对褒贬不一的评价,面对各种各样的传闻,倾诉权在自己身上,决定权无法改变. 探讨Qt被裁之后,转念来说说 “Symbian在中国是怎么猝死的. ”最终迫使nokia裁去的Qt会不会也瞬间猝死. nokia的局面是否会被WP扭转. 曾经Symbian在市场中覆盖面很广.

Qt那点事儿(一)

- niko - C++博客-首页原创精华区
第一回 Signal和Slot是同步的还是异步的.   我们知道Qt以他的signal和slot机制独步天下. 但大家在用的时候有没有注意过,signal和slot之间是异步的,还是同步的呢. 有人说是同步的,有人说是异步的,也有人说要看当时你的人品.   为此贫道,特别做了以下几个测试:.      First,在main()主函数里,设置两个基于QObject为父类的对象a和b,a触发signal,b接受signal.

Dijia 从 Nokia 收购 Qt

- - 博客 - 伯乐在线
Nokia在去年三月份将Qt团队外包给了芬兰的一家名叫Digia的公司. 据 国外媒体thenextweb报道,今天Nokia正式将Qt开源软件技术卖给了Digia. 而Digia预计在掌管这个项目后将其推广到Android、iOS和Windows 8 平台. Digia主要目标是借助Qt生态系统加强自身的研发能力,并且将这项技术推广到Android和iOS智能手机平台,也包括了微软的Windows 8系统,之前Nokia就有意在平板上使用Windows 8系统.

C/C++编程的现代习惯

- - idea's blog
相对于汇编语言是一门操作 CPU 寄存器的语言, C/C++ 是一门操作内存的语言, 这是传统的观点. 但现代的程序应用开发, 大多是把 C/C++ 当作一门应用层语言, 所以必须适当地减少对内存的关注. 这也是本文所要讲的 - C/C++ 编程的现代习惯.. 在一些古董级的编程书里, 你绝对看不到返回结构体或者类的实例, 它们告诉你"不能返回局部变量的内存".

N9 + Qt 很给力——看看 N9 的那些 Qt App 们

- Brant - 爱范儿 · Beats of Bits
也许德国,瑞典,美国,日本的诺基亚玩家应该羡慕中国用户,因为我们不久就能买到行货诺基亚 N9 了. 跟两年前的 N900 不同,诺基亚这次非常重视中国市场,并跟第三方应用商展开广泛合作,行货 N9 将会内置非常多的中文应用程序,而且都是基于 Qt 开发的. 诺基亚在 Qt 开发站点上放出了几段视频,向开发者们展示 N9 + Qt 的流畅程度和开发优势.

Qt 将移至开放式管理

- 逸川 - LinuxTOY
在最近举行的 XDC2011 会议上,Nokia 宣布将 Qt 移至开放式管理模式. Qt 将拥有一个独立的域名 qt-project.org (尚未上线),由一个专注于 Qt 的非营利性组织管理. 所有的技术上的决定,包括项目发展方向,将会由包括贡献者、审核者和维护者组成的社区团体共同决定. 预期 qt-project.org 将会在下个月的 Qt 开发者日之前上线.

诺基亚开除QT团队

- - 博客 - 伯乐在线
诺基亚的裁员终于波及到了QT,并不完全出人意料,在其开发平台“战略性转移”后,这只是一个时间问题. 在诺基亚计划解雇的1万名雇员中,有700位开发者, 其中100位是QT核心开发者( 快照). 诺基亚是QT开源项目的 最主要资助者,Mirko Boehm 说,QT 的核心成员就100人. 因此诺基亚事实上是解雇了整个QT团队.