|
前段時(shí)間終于把設(shè)備管理上位機(jī)完成的差不多了,用了差不多有半個(gè)月的時(shí)間了,因?yàn)閷?duì)QT還不是特別的熟悉,所以中間還是摸索QT的過(guò)程。這個(gè)上位機(jī)程序用到了多線程,數(shù)據(jù)庫(kù)操作,網(wǎng)絡(luò)套接字還有一些界面操作。使用的IDE我選用的是QT CREATOR,個(gè)人覺(jué)得還是很好用的,里面集成了QT DESIGNER,QT HELP,,QT DEBUG(雖然暫時(shí)我還沒(méi)用過(guò)調(diào)試器,都是使用Qdebug打印信息和QMesseageBox輸出對(duì)話框來(lái)調(diào)試的),QT CREATOR編輯環(huán)境也是相當(dāng)不錯(cuò)的,特別是自動(dòng)補(bǔ)全功能,呵呵不用記那么多類了,還有對(duì)類和函數(shù)或?qū)ο驠1可以看到幫助文檔,但是有個(gè)前提就是這個(gè)類的頭文件你必須聲明正確,而卻你的對(duì)象函數(shù)也必須寫正確了,否則就看不到文檔了。在編寫過(guò)程也碰到了很多問(wèn)題,現(xiàn)在就回憶一遍吧。
問(wèn)題1:在多線程的編寫中,我們都知道run()里面的函數(shù)對(duì)象都是在新線程中運(yùn)行的,那么新線程怎么和老線程交互。
答案:編寫多線程類的時(shí)候,我們把需要和主線程交互的對(duì)象放在線程類中,這樣在主線程類中定義一個(gè)線程類對(duì)象,這樣主線程可以訪問(wèn)這個(gè)線程類的對(duì)象,當(dāng)然如果是直接訪問(wèn),那就要這個(gè)對(duì)象是PUBLIC的了,如果不是就要通過(guò)線程類對(duì)象函數(shù)了。同時(shí)run因?yàn)槭蔷程類的成員函數(shù),那么他也可以訪問(wèn)同一個(gè)對(duì)象的成員。所以線程類對(duì)象的這個(gè)成員變量就相當(dāng)于多線程的共享變量了,所以我們要互斥訪問(wèn),我們可以在線程類里面定義一個(gè)鎖。
問(wèn)題2:窗口操作只能運(yùn)行于主線程(可能原因?yàn)榇翱谛枰猀Application的支持,而QApplication是定義在主線程中的,窗口運(yùn)行在主事件循環(huán)中,而次線程的exec只是屬于它的次線程循環(huán))。當(dāng)在次線程中QMessageBox();錯(cuò)誤如下: ASSERT failure in QWidget: "Widgets must be created in the GUI thread.", file kernel/qwidget.cpp, line 1069 QObject::killTimers: timers cannot be stopped from another thread。我想要在此線程做了某個(gè)操作后就彈出個(gè)對(duì)話框進(jìn)行提示,那該怎么辦。、
答案:既然主線程負(fù)責(zé)窗口操作,那么我們就把這個(gè)事交給主線程來(lái)做。我是在次線程中emit一個(gè)信號(hào),而這個(gè)信號(hào)連接的槽運(yùn)行在主線程中,所以讓這個(gè)槽來(lái)QMessageBox;這也說(shuō)明了,如果一個(gè)功能在一個(gè)地方運(yùn)行不了,那么我們可以通過(guò)信號(hào)槽機(jī)制使得它在別的地方運(yùn)行,不能運(yùn)行的地方拋信號(hào),能運(yùn)行的地方定義槽,信號(hào)和槽進(jìn)行合適的連接,一般在構(gòu)照函數(shù)中(對(duì)象的開(kāi)始函數(shù)哦)。在help文檔中有一句The main event loop receives events from the window system and dispatches these to the application widgets. Generally speaking, no user interaction can take place before calling exec(). 也就是說(shuō)一切的窗口操作事件都是由a.exec分配的,分配到各個(gè)子窗口部件中的。
問(wèn)題3:程序運(yùn)行時(shí)候出現(xiàn)window runtime error,
答案:一般這個(gè)都是內(nèi)存訪問(wèn)不當(dāng)造成的,訪問(wèn)越界,訪問(wèn)非法數(shù)據(jù)等等,我的問(wèn)題是我定義了一個(gè)QBitArray ba;然后直接ba.setbit(5,0);因?yàn)閎a的一開(kāi)始空間為0,所以setbit導(dǎo)致內(nèi)存覆蓋。所以我要使用的時(shí)候必須ba.setsize(size)才可以。
問(wèn)題4:使用query創(chuàng)建表的時(shí)候表名不能以數(shù)字開(kāi)頭,而且不能數(shù)字和字母多次混合,例如下面的表名老是會(huì)報(bào)語(yǔ)法錯(cuò)誤。錯(cuò)誤表名: 20060801 錯(cuò)誤原因:不能以數(shù)字開(kāi)頭 W2006w0801 錯(cuò)誤原因:數(shù)字和字母不能多次混合正確表名; W20060801既字母+數(shù)字。
答案:我的表名就以字母開(kāi)頭吧,呵呵,當(dāng)然廢話,怎么搞想一切辦法啊。
問(wèn)題5:網(wǎng)絡(luò)連接,連接不上主機(jī)時(shí)候,(意思就是說(shuō)ping不通主機(jī)的時(shí)候)老長(zhǎng)時(shí)間等待,又找不到QsqlSocket的阻塞機(jī)制,長(zhǎng)時(shí)間等待會(huì)使得用戶覺(jué)得程序當(dāng)了
答案:,所以最后我使用了一個(gè)定時(shí)器,一連接時(shí)候就定時(shí),4秒沒(méi)有連接上的會(huì)就提示連接失敗,這個(gè)時(shí)間也可以調(diào)小一點(diǎn)的。連接上的 話,這個(gè)定時(shí)器就什么都不做,和定時(shí)器的協(xié)調(diào)時(shí)通過(guò)一個(gè)標(biāo)志變量來(lái)完成的。
問(wèn)題6:操作數(shù)據(jù)庫(kù)的時(shí)候查詢很慢,一開(kāi)始是使用QsqlQuery+QTableWidget就是建立了索引還是好慢
答案:改成QtableModel+QTableView快多了,一萬(wàn)條的記錄秒殺。所以說(shuō)還是要清楚你使用的工具啊,QT的這個(gè)工MODEL類很好很強(qiáng)大。
|
|