Qt4问题集锦
一、Qt程序發(fā)布后加載的jpg、jpeg圖片不可見(jiàn)
問(wèn)題的提出:
最近在客戶機(jī)器上部署安裝QT編寫的軟件,發(fā)現(xiàn)只要是jpg、jpeg格式的圖片都無(wú)法顯示出來(lái)。最后發(fā)現(xiàn)必須按如下述步驟才能顯示jpg、jpeg格式的圖片: 1、 在你主啟動(dòng)程序即exe同一目錄下新建一個(gè)目錄,目錄名必須和QT安裝目錄下的imageformats目錄同名。也即新建一個(gè)名為imageformats的文件夾。 2 、找到QT安裝目錄下C:\Qt\4.8.5\plugins\imageformats子目錄,將該子目錄下的qjpeg4.dll文件復(fù)制到步驟1中新建的imageformats目錄即可。 此時(shí)再次啟動(dòng)主程序,現(xiàn)在發(fā)現(xiàn)jpg、jpeg格式的圖片可以顯示出來(lái)了。說(shuō)明:步驟2中紅色路徑我QT的安裝路徑,你的路徑可能和我這不一樣,請(qǐng)自行更改。
?
二、運(yùn)行Qt程序時(shí)碰到QWidget: Must construct a QApplication before a QPaintDevice
問(wèn)題的提出:
之前編譯Qwt源碼生成qwtd.dll,qwt.dll,然后在工程.pro文件中使用時(shí)引入Qwt模塊:
DEFINES += QT_DLL QWT_DLL INCLUDEPATH += C:/QtSDK/Desktop/Qt/4.8.1/mingw/include/Qwt LIBS += -L"C:/QtSDK/Desktop/Qt/4.8.1/mingw/lib" -lqwtd LIBS += -L"C:/QtSDK/Desktop/Qt/4.8.1/mingw/lib" -lqwt結(jié)果程序運(yùn)行時(shí),出現(xiàn)QWidget: Must construct a QApplication before a QPaintDevice
網(wǎng)上搜索的結(jié)果是Releases和DEBUG版本的庫(kù)混在一起了,雖然他們是不同的名字(Debug版本帶個(gè)d),但是一直不明白。我生成release版后,直接運(yùn)行.exe時(shí)發(fā)現(xiàn)提示缺少qwtd.dll庫(kù),
此時(shí)才發(fā)現(xiàn)果然是庫(kù)的問(wèn)題,生成release版卻調(diào)用了debug版的庫(kù)qwtd.dll。
問(wèn)題解決:將.pro文件中Qwt模塊引入代碼改為:
DEFINES += QT_DLL QWT_DLL INCLUDEPATH += C:/QtSDK/Desktop/Qt/4.8.1/mingw/include/Qwt CONFIG(debug,debug|release) { unix|win32: LIBS += -L"C:/QtSDK/Desktop/Qt/4.8.1/mingw/lib" -lqwtd } else { unix|win32: LIBS += -L"C:/QtSDK/Desktop/Qt/4.8.1/mingw/lib" -lqwt }此時(shí),編譯成debug版則只會(huì)調(diào)用qwtd.dll,而生成release版則只會(huì)調(diào)用qwt.dll。
?
三、Qt編寫上位機(jī)一定要初始化變量以及謹(jǐn)慎操作指針(尤其是QWidget控件指針)
背景:在編寫QT上位機(jī)界面時(shí),界面在運(yùn)行的時(shí)候經(jīng)常出現(xiàn)卡死或者直接掛掉的怪現(xiàn)象。
正文:上位機(jī)有個(gè)函數(shù)為check_receive();該函數(shù)的作用為定時(shí)調(diào)用循環(huán)檢測(cè)USB是否有數(shù)據(jù)。若有,則將信息打印到界面窗體上。界面上有兩個(gè)QTableWidget窗體
"ui->can1tableWidget與ui->can2tableWidget",根據(jù)傳上來(lái)的的數(shù)據(jù)某個(gè)字節(jié)信息為1、或2來(lái)打印到對(duì)應(yīng)的窗體上。代碼如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | QTableWidget *canselWidget = NULL; unsigned?int?CANSelCnt; if(CANData.CANSel == 1) { ????CANSelCnt = 第1個(gè)窗體顯示的行數(shù);????//偽代碼 ????canselWidget = ui->can1tableWidget ; } else?if(CANData.CANSel == 2) { ????CANSelCnt = 第2個(gè)窗體顯示的行數(shù);????//偽代碼 ????canselWidget = ui->can2tableWidget ; } //接著即使用canselWidget來(lái)對(duì)界面進(jìn)行操作。 |
接著,總會(huì)出現(xiàn),QT上位機(jī)界面直接卡死甚至掛掉的問(wèn)題。觀察現(xiàn)象發(fā)現(xiàn),APP在顯示數(shù)據(jù)窗體時(shí)即瘋狂地新增新的行數(shù)。再研究代碼,然后將CANSelCnt打印出來(lái),發(fā)現(xiàn)其值為一個(gè)很大的隨機(jī)值。
解決方案:CANSelCnt 在定義的時(shí)候要初始化!!!
接著運(yùn)行上位機(jī)發(fā)現(xiàn),APP顯示數(shù)據(jù)窗體不再瘋狂的新增行數(shù)了。可還是出現(xiàn)掛掉的現(xiàn)象!!
進(jìn)一步調(diào)試才發(fā)現(xiàn)若是CANData.CANSel的值不是為1、2那會(huì)出現(xiàn)什么情況! 就會(huì)對(duì)canselWideget這個(gè)NULL指針進(jìn)行操作!更改代碼如下:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | switch(CANData.CANSel) { ????case?1: ????????CANSelCnt = 第1個(gè)窗體顯示的行數(shù);????//偽代碼 ????????canselWidget = ui->can1tableWidget ; ?????????break; ????case?2: ????????CANSelCnt = 第2個(gè)窗體顯示的行數(shù);????//偽代碼 ????????canselWidget = ui->can2tableWidget ; ????????break; ????default: ????????// 防止后續(xù)代碼對(duì)空指針進(jìn)行操作,直接返回。 ????????return; } |
總結(jié):
1、此處代碼寫的非常不小心,犯如此低級(jí)的錯(cuò)誤卻花費(fèi)了1天多的時(shí)間(還以為是下位機(jī)沒(méi)配置好!)!下次一定要把握住程序運(yùn)行的每個(gè)通路,杜絕此現(xiàn)象再次發(fā)生。
2、由于之前一直在寫下位機(jī)代碼,所以不賦初值的習(xí)慣也帶入到這里,出了這次慘痛教訓(xùn)!
?
(以下討論僅針對(duì)下位機(jī))在下位機(jī),為何會(huì)經(jīng)常出現(xiàn)不賦初值的情況發(fā)生。(應(yīng)該說(shuō)是在聲明的時(shí)候不會(huì)賦初值。)
首先,最重要的是,下位機(jī)保存全局變量的區(qū)域?yàn)榈綦娨资^(qū)域,所以得到的變量值會(huì)為默認(rèn)"0"值,嚴(yán)謹(jǐn)?shù)淖龇ㄟ€是會(huì)初始化全局變量。
其次,在多個(gè)".c"文件包含一個(gè)".h"文件的情況下,若在".h"文件中賦初值,則相當(dāng)于在其內(nèi)即聲明又定義了,那么編譯時(shí),即會(huì)出現(xiàn)如下報(bào)錯(cuò):keil *** ERROR L104: MULTIPLE PUBLIC DEFINITIONS (報(bào)錯(cuò)信息不完整,只挑了重點(diǎn)部分)。所以說(shuō)有多個(gè)".c"文件需要包含該".h"文件時(shí),不能進(jìn)行變量的定義,只能進(jìn)行聲明!然后在"main函數(shù)"內(nèi)對(duì)其進(jìn)行初始化操作,否則會(huì)出現(xiàn)以上錯(cuò)誤,即重復(fù)定義!
? ? ?那么多個(gè)"c"文件包含一個(gè)".h"文件具體該如何操作呢?
我自己當(dāng)時(shí)的錯(cuò)誤想法既是:
在".h"文件內(nèi),聲明全局變量、函數(shù),譬如uchar aa;void sum(uchar aa); 然后多個(gè)".c"文件#include該".h"文件,結(jié)局很顯然,重復(fù)定義錯(cuò)誤跑不掉。
何不使用?#ifndef?#define?#endif ?結(jié)果證明并沒(méi)有什么卵用。
正確的做法是,
在".c"文件內(nèi)聲明全局變量、函數(shù),譬如uchar aa;void sum(uchar aa);,并在".c"文件內(nèi)實(shí)現(xiàn)該函數(shù)。
然后,在".h"文件,將變量aa,函數(shù)void sum(uchar aa);聲明為extern,這樣,其他".c"包含該".h"文件即不會(huì)提示重復(fù)定義,也可以調(diào)用其內(nèi)部的函數(shù)。
其實(shí)這種做法其實(shí)相當(dāng)于某個(gè)需要調(diào)用該".c"文件的其他"XXX.c"文件在其文件內(nèi) extern 該“.c"文件內(nèi)實(shí)現(xiàn)的函數(shù)及定義的變量。若是多個(gè)文件需要使用使用,每個(gè)".c"文件都需 extern 同樣的變量和函數(shù),顯然在做重復(fù)工作,于是就將它放在一個(gè)".h"文件,多個(gè)".c"文件需要調(diào)用時(shí)直接包含該".h"文件就可以實(shí)現(xiàn) extern 了。
總之,要養(yǎng)成良好的編程習(xí)慣,編寫下位機(jī)時(shí)最好不要在.h文件去定義一個(gè)變量,更不能在.h文件去初始化變量。變量定義與初始化在.c文件進(jìn)行,若多個(gè)外部.c文件需要調(diào)用,則在.h文件中添加extern進(jìn)行外部聲明即可。
轉(zhuǎn)載于:https://www.cnblogs.com/King-Gentleman/p/5986331.html
總結(jié)
- 上一篇: (转) 一张图解AlphaGo原理及弱点
- 下一篇: java代码代替xml实现图片