??Qt的官方文檔雖然并沒有明確說明,不能在子線程中操作UI,但是,因?yàn)镼t是事件循環(huán)機(jī)制,所有的UI事件都是在主線程中處理的,如果在子線程中直接操作UI,就會(huì)存在線程安全問題,嚴(yán)重時(shí)候會(huì)使程序掛掉。
??但是有些場(chǎng)景確實(shí)需要在子線程中操作UI怎么辦?以下是幾種常用的解決方案:
??1. 使用信號(hào)槽機(jī)制
??這種方式是當(dāng)子線程中需要對(duì)ui對(duì)象進(jìn)行操作時(shí),發(fā)出一個(gè)信號(hào),在與之連接的槽中處理ui操作。信號(hào)和槽的連接方式必須是BlockingQueuedConnection 或QueuedConnection 的連接方式連接。
??2. 使用自定義event
??在子線程中通過QCoreApplication::postEvent 發(fā)出自定義的event,在對(duì)應(yīng)的ui對(duì)象中重寫customevent中處理自定義的event 。
??3. 使用QMetaObject::invokeMethod()函數(shù)
??該函數(shù)是一個(gè)靜態(tài)函數(shù),可以直接使用,用于調(diào)用對(duì)象的元對(duì)象方法 。該函數(shù)功能很強(qiáng)大,這里是用到了其可以在不同線程之間調(diào)用對(duì)象方法的特性。
??如果是新代碼,可以在程序設(shè)計(jì)之初就處理好子線程與UI操作之間的協(xié)調(diào)處理,這種情況比較好辦,可以使用方法1和方法2進(jìn)行處理。但是如果是維護(hù)歷史代碼,重新做設(shè)計(jì)肯定是不現(xiàn)實(shí)的,所以就需要使用方法3進(jìn)行處理,在子線程中操作UI的代碼段,修改為QMetaObject::invokeMethod函數(shù)調(diào)用,可以做到最小程度的代碼修改,下面給出具體例子:文章來源:http://www.zghlxwxcb.cn/news/detail-774874.html
// 在子線程中調(diào)用
int rowCount = 0;
REPORT_DE_INFO reportInfo;
bool b = QMetaObject::invokeMethod(this, "initTablewidget", Qt::BlockingQueuedConnection, Q_RETURN_ARG(int, rowCount), Q_ARG(REPORT_DE_INFO&, reportInfo));
??參數(shù)說明:
?? 參數(shù)1:調(diào)用對(duì)象指針
?? 參數(shù)2:調(diào)用的方法名
?? 參數(shù)3:連接方式,與信號(hào)槽連接函數(shù)connect的最后一個(gè)參數(shù)相同。對(duì)于這里是維護(hù)歷史代碼的場(chǎng)景,建議使用BlockingQueuedConnection,原來代碼的執(zhí)行邏輯一定是先執(zhí)行完函數(shù)后才繼續(xù)往下走,如果這里不給阻塞住,函數(shù)還沒執(zhí)行完,子線程就會(huì)繼續(xù)往下走,很顯然這與原來的代碼邏輯并不相同,很可能會(huì)出現(xiàn)錯(cuò)誤
?? 參數(shù)4:Q_RETURN_ARG宏,用來接收函數(shù)的返回值,宏的第1個(gè)參數(shù)是返回值類型,第2個(gè)參數(shù)是接收返回值的變量名
?? 參數(shù)5:Q_ARG宏,用來向函數(shù)傳遞參數(shù),宏的第1個(gè)參數(shù)是函數(shù)參數(shù)的類型,第2個(gè)參數(shù)是傳遞參數(shù)的變量名,如果函數(shù)有多個(gè)參數(shù),可以繼續(xù)往下使用Q_ARG宏來傳遞
?? 返回值:bool類型,執(zhí)行成功或者失敗
?? 注意:執(zhí)行的函數(shù)一定要是槽函數(shù),否者回執(zhí)行失敗文章來源地址http://www.zghlxwxcb.cn/news/detail-774874.html
到了這里,關(guān)于Qt不能在線程函數(shù)操作UI的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!