網(wǎng)站審批需要什么手續(xù)東莞優(yōu)化seo
引出
????????UI程序之所叫UI程序,是因?yàn)樾枰c用戶(hù)有交互,用戶(hù)交互一般是通過(guò)鼠標(biāo)鍵盤(pán)等的輸入設(shè)備,那UI程序就需要有能隨時(shí)響應(yīng)用戶(hù)交互的能力。
一個(gè)C++程序的main函數(shù)大概是下面這樣:
int main()
{...return 0;
}
我們?nèi)绾问钩绦蚰茈S時(shí)可以響應(yīng)用戶(hù)交互呢?一個(gè)比較簡(jiǎn)單的設(shè)計(jì)就是通過(guò)while循環(huán):
int main()
{while (1) {獲取用戶(hù)輸入;處理用戶(hù)輸入;}return 0;
}
有時(shí)一個(gè)事件的處理可能稍微會(huì)多花一點(diǎn)時(shí)間,如果是上面這樣,在處理一個(gè)事件時(shí)就不能響應(yīng)其他事件了,所以我們需要一個(gè)隊(duì)列,系統(tǒng)可以將新事件放到隊(duì)列里:
int main()
{while(1) { event = getEventFromQueue()dealEvent(event);}
}
原理
????????在Qt中,事件循環(huán)是一種機(jī)制,用于處理各種異步事件。事件循環(huán)通過(guò)一個(gè)事件隊(duì)列來(lái)管理和調(diào)度事件,當(dāng)隊(duì)列中有事件時(shí),事件循環(huán)會(huì)從隊(duì)列中依次取出事件并處理,直到隊(duì)列為空或者事件循環(huán)被中斷。
????????事件循環(huán)首先是一個(gè)無(wú)限“循環(huán)”,程序在exec()里面無(wú)限循環(huán),能讓跟在exec()后面的代碼得不到運(yùn)行機(jī)會(huì),直至程序從exec()跳出。從exec()跳出時(shí),事件循環(huán)即被終止。
????????其次,之所以被稱(chēng)為“事件”循環(huán),是因?yàn)樗芙邮帐录?#xff0c;并處理之。當(dāng)事件太多而不能馬上處理完的時(shí)候,待處理事件被放在一個(gè)“隊(duì)列”里,稱(chēng)為“事件循環(huán)隊(duì)列”。當(dāng)事件循環(huán)處理完一個(gè)事件后,就從“事件循環(huán)隊(duì)列”中取出下一個(gè)事件處理之。當(dāng)事件循環(huán)隊(duì)列為空的時(shí)候,它和一個(gè)啥事也不做的永真循環(huán)有點(diǎn)類(lèi)似,但是和永真循環(huán)不同的是,事件循環(huán)不會(huì)大量占用CPU資源。事件循環(huán)的本質(zhì)就是以隊(duì)列的方式再次分配線程時(shí)間片。
事件是如何產(chǎn)生的?
????????事件的產(chǎn)生可以分為兩種:
????????程序外部產(chǎn)生:指系統(tǒng)產(chǎn)生的事件,例如鼠標(biāo)按下(MouseButtonPress)、按鍵按下(KeyPress)等。Qt通過(guò)捕捉系統(tǒng)事件,將其封裝成自己的QEvent類(lèi),再將事件發(fā)送出去。
????????程序內(nèi)部產(chǎn)生:指在代碼中手動(dòng)創(chuàng)建一個(gè)事件,然后通過(guò)sendEvent/postEvent將事件發(fā)送到事件循環(huán)中。其中,sendEvent是阻塞型的發(fā)送方式,會(huì)等待事件處理完成后再繼續(xù)執(zhí)行;而postEvent是非阻塞型的發(fā)送方式,會(huì)將事件放入事件隊(duì)列中,并立即返回。
本質(zhì)
????????QEventLoop即Qt中的事件循環(huán)類(lèi)。主要接口如下:
//exec是啟動(dòng)事件循環(huán),調(diào)用exec以后,調(diào)用exec的函數(shù)就會(huì)被“阻塞”,直到EventLoop里面的while循環(huán)結(jié)束。
int exec(QEventLoop::ProcessEventsFlags flags = AllEvents)
//exit是退出事件循環(huán);
void exit(int returnCode = 0)
bool isRunning() const
//processEvents是及時(shí)處理隊(duì)列中的事件(這個(gè)很有用)
bool processEvents(QEventLoop::ProcessEventsFlags flags = AllEvents)
void processEvents(QEventLoop::ProcessEventsFlags flags, int maxTime)
void wakeUp()
示意圖:
????????這里有個(gè)問(wèn)題,exec阻塞了當(dāng)前函數(shù),還怎么退出EventLoop呢?
????????答案是:在派發(fā)事件后,某個(gè)事件處理的函數(shù)中,達(dá)到事件退出條件時(shí),調(diào)用exit函數(shù),將EventLoop中的退出標(biāo)識(shí)設(shè)為true。
????????一般的Qt程序,main函數(shù)中都有一個(gè)QCoreApplication/QGuiApplication/QApplication,并在末尾調(diào)用 exec。
????????創(chuàng)建Qt Core Application時(shí)使用的是QCoreApplication,創(chuàng)建Qt Widgets Application時(shí)使用的是QApplication,創(chuàng)建Qt Quick Application時(shí)使用的是QGuiApplication。
其他
//例1:
int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget_ScrollBar w;w.show();/*w.show()不生效;界面不會(huì)輸出;UI程序中事件循環(huán)實(shí)質(zhì)是:通過(guò)UI來(lái)進(jìn)行事件的循環(huán)處理*///return a.exec();return 0;
}//例2:
int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget_ScrollBar w;w.show();a.exec();//阻塞后續(xù)程序執(zhí)行/*只有exec()退出,事件循環(huán)結(jié)束,才會(huì)輸出Hello World*/qDebug() << "Hello World";return 0;
}