分析Qt編程習(xí)慣 主窗體創(chuàng)建問題
本文介紹的是分析Qt編程習(xí)慣 主窗體創(chuàng)建問題,要知道,并不是只有初學(xué)者才會犯錯。最近發(fā)現(xiàn)了一些有意思的問題,值得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十分標(biāo)準(zhǔn),非常符合筆者平時寫Qt程序書寫main函數(shù)的習(xí)慣, 孰料想竟然是個錯誤的習(xí)慣,而且問題很嚴(yán)重哦。 給個提示:在程序退出時會aborted。
如果還沒想出來是什么問題,嘿嘿,沒關(guān)系,看了下面的答案你就明白了。
在這段程序里QApplication實例創(chuàng)建在stack上,生命期是main的大括號內(nèi),而mw則通過new創(chuàng)建在heap上,在程序退出時才會被析構(gòu)。 換句話說,mw的生存期長于application的生存期…..這可是Qt編程的大忌, 因為在Qt中所有的Paint Device都必須要在有QApplication實例的情況下創(chuàng)建和使用。
不過如果把這個程序?qū)懗鰜磉\行一下,未必會出現(xiàn)我說的aborted的問題,大多數(shù)代碼類似的程序都能安全的運行(這也是為什么用了那么多年的Qt從來沒有注意過這個問題,并且養(yǎng)成了我錯誤的編程習(xí)慣。)。這里的trick在于application退出時mw已經(jīng)被關(guān)閉,mw中的所有Paint Device一般都不會被訪問到了, 所以這個錯誤隱藏在很深的陰暗角落, 偷偷地嘲笑我們呢!
要想試驗這個問題也很簡單,把load的參數(shù)換成本地文件 test.html, 并把下面的內(nèi)容寫進(jìn)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”。
既然提出的問題,當(dāng)然也要給出解決的方案。 有兩種可行的方法避免該錯誤。 一個當(dāng)然是糾正一下編程習(xí)慣,對mw不要用new的方式創(chuàng)建,改在stack上創(chuàng)建,如下代碼:
- #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屬性。該屬性標(biāo)示窗體會在close時被析構(gòu),這樣就保證不會留存在application析構(gòu)之后了,是個很好的辦法。
代碼如下:
- #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();
- }
發(fā)現(xiàn)問題和解決問題是件很有樂趣的事情,大家不要把時間都浪費在猜測上,要多動手多思考才能進(jìn)步!
Qt Jambi也存在類似的問題,如果以程序啟動的代碼塊去啟動QApplication,在程序運行過程中,一些資源回收會報出Null指針錯誤,這些錯誤,通過debug,最終都會指向QWidget這個類。當(dāng)把QApplication啟動的執(zhí)行程序移出main函數(shù),問題迎刃而解。要多注意細(xì)節(jié)。
小結(jié):分析Qt編程習(xí)慣 主窗體創(chuàng)建問題的內(nèi)容介紹完了,希望本文對你有所幫助!更多內(nèi)容請參考編輯推薦。