問題背景與描述
我這兩天一直想把YOLOv5上加個訓練的界面,把控制臺的輸出重定向到一個PyQT5寫的界面上,然后我很順序的寫好了一個簡單的測試,發現可以重定向了,一直實時獲取輸出了。代碼如下: 然后我就寫了個界面,讓控制臺顯示到界面的texteditor中,我知道訓練是一個長耗時的操作過程,所以我單獨開啟了一個QThread線程來完成,然后在線程中發送獲取的控制臺輸出文本給界面主線程,完成界面刷新。以前我用QT C++就是這樣干的,所以這個肯定可以。于是寫一個線程類,大致如下:
classTrainTask(QThread): textWritten=QtCore.pyqtSignal(str) def__init__(self,command_txt): QThread.__init__(self) self.cmd_txt=command_txt def__del__(self): self.wait() defrun(self): self.textWritten.emit("testrefreshui") foriinrange(1000): self.textWritten.emit("testrefreshui") self.msleep(1)
然后在界面類中通過一個按鈕點擊開啟它, 然后它就會開始發送數據到界面類指定方法outputWritten中。綁定按鈕響應事件:
self.start_training_btn.clicked.connect(self.start_traning_action)
點擊按鈕執行:
my_train = TrainTask(cmd_txt + params)my_train.textWritten.connect(self.outputWritten)my_train.start()我以為上述代碼是天衣無縫,這樣就大功告成了,實際上是界面直接卡死了,還有天理嗎?多線程居然阻塞返回之后才刷新?!!!
問題現象與解決
把線程中的for訓練語句去掉,單獨發消息跟界面類,發現可以成功。一旦放開,在run方法中使用for或while之后,就會一直等到結束才返回刷新界面,說明開啟的線程沒有異步,還是阻塞執行,導致界面卡死。
01
嘗試一:
網上一通搜索,有人告訴我說必須先定義一個work類,然后把work類移到QThread線程實例中,測試了是個錘子,沒用!
02
嘗試二:
說在線程run方法中導致CPU無法輪詢,一定就不是很合理的解釋,必須要用線程的sleep方法才行,測試了還是個錘子,沒用!
03
解決方法:
之前的卡死界面線程的代碼沒有錯的,錯就錯在調用方法,錯誤的調用方式:
my_train=TrainTask(cmd_txt+params) my_train.textWritten.connect(self.outputWritten) my_train.start()
重點來了,正確的調用方式如下:
self.my_train = TrainTask(cmd_txt + params)self.my_train.textWritten.connect(self.outputWritten)self.my_train.finished_signal.connect(self.do_finish_action)self.my_train.finished.connect(self.my_train.deleteLater)self.my_train.start()self.start_training_btn.setEnabled(False)self.stop_training_btn.setEnabled(True)
總結一句話:
一定要把線程變量聲明為界面類的成員變量,而不是方法中臨時變量,是臨時變量必然卡死界面,無法刷新,這個是折騰一天得到的教訓!網上搜不到!!! 解決了這個問題之后,我很快寫好了一個YOLOv5從界面直接開啟訓練的演示界面,如下圖所示,準備好數據,點幾下按鈕就可以訓練YOLOv5,生成模型了!
后來我又添加了一個高級參數設置,發現更好用了!
從此訓練YOLOv5, 只要標注好數據,剩下點點鼠標就好了!
-
界面
+關注
關注
0文章
59瀏覽量
15663 -
多線程
+關注
關注
0文章
278瀏覽量
20070 -
pyqt
+關注
關注
0文章
12瀏覽量
4327
原文標題:有坑 | PyQT多線程無法刷新,導致界面卡死
文章出處:【微信號:CVSCHOOL,微信公眾號:OpenCV學堂】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論