一、前言
眾所周知,只要涉及界面開發,都有一句話:禁止在子線程里增刪改查界面。
也就是所謂的:主線程更改界面,子線程做運算。
有時候發現線程不能改變界面是非常不方便的,而上面的兩句話也只是“原則上”,也就是說其實是可以的。
至於有后果:【個人推測】
APP在主線程中有自己的一套消息循環,如界面繪制、重繪、更新等,如果程序員在子線程中加上這些操作,可能會產生沖突,到時候軟件意外崩潰,幾乎是找不到原因的啊!!!
所以本文的投機取巧要慎用,反正我不管沖了!!
二、舉例
我做過MFC、C#、Python、Matlab【不提供線程】,幾乎都是這個原則,今天把這個原則深入研究一下。
三、Qt線程概述
Qt庫提供線程一般有兩種,加上C++自己的線程,就是三種。分別是:QThread子類、QObject子類+moveToThrad、std::thread+其他線程函數。
前兩種都是用來后台計算,我還沒有用來改變過界面,往往通過信號與槽來讓main線程修改界面,根據我的推測【還沒試驗,確實沒必要,只用來做計算應該也夠了】,是可以在他們依附的子線程里修改界面的,如何實現看下面。
第三種C++自己的線程開啟函數,也就是通過線程對象+線程函數+入參的形式開啟一個線程。
四、如何在線程里訪問界面
仔細看Qt窗口項目代碼
就是這個ui指針,它指向的Mainwindow對象,Qt內部自己將ui指針指向了自己的mainwindow.ui界面文件,所以總結來說就是:
界面也是個對象。
既然界面也是個對象,那我把這個對象當做參數傳遞到子線程中,是可行的。
五、實現
1、在mainwindow.h定義線程入口函數
void getWltData(QString path);
2、mainwindow.cpp中實現並訪問界面
void Mystack::getWltData(QString path) { ui->label_84->setText("子線程訪問界面"+path); }
3、開啟線程
void Mystack::on_pushButton_17_clicked() { std::thread t(&Mystack::getWltData,this,ui->lineEdit_71->text()); t.detach(); }
總結:
想要在子線程中訪問界面,只要把界面對象傳遞給子線程函數即可。
注意:
線程函數要定義成類的函數,因為這樣才能訪問private屬性的ui,如果是全局函數,則沒有this指針,即使傳遞this進去也不能訪問到private對象;
然后類函數默認有一個this入參的;
這樣做有何不良反應還沒發現。