【Python成長之路】用python製作一款錄屏小工具(2)--moveToThread()方法的使用

哈嘍大家好,我是鵬哥。

今天我們把上週錄屏小工具的一些細節進行詳細說明下,因此這次的主題是 —— QThread的正確使用

1

寫在前面

我們先回顧下上次博客是如何實現pyqt5的多線程功能的?

class WorkThread(QThread):    def __init__(self, n):        super(WorkThread, self).__init__()        self.n = n
    def run(self):        XXXXX

        簡單來說,就是通過繼承QThread類,並修改run方法來實現的。但是有一次在網上看帖子時,發現QT大神們說:

不要將業務邏輯代碼放到QThread類中,QThread類是用於管理線程的(大致是這個意思)

    那要怎麼實現多線程纔是正確科學的呢?答案是使用moveToThread()方法來實現。

        

2

效果展示

這裏爲了重點演示多線程代碼,因此將錄屏功能代碼進行了註釋。以上功能通過點擊錄屏(自定義或全屏)來 啓動線程,點擊結束錄屏來結束線程。

3

知識串講(敲黑板啦)

爲了實現QT5的多線程功能,這裏有2個知識點需要學習和了解。

(1)信號與槽

signal = pyqtSignal(str)

    首先需要在自己的類中,使用pyqtSignal()方法來定義一個信號變量,其中如果要傳遞的信號是str類,則需要聲明下str;如果是int類的信號,則這樣定義:

signal = pyqtSignal(int)

在信號定義後,自然要有個槽來接受信號,即使用以下代碼:

# 創建線程self.workobject = WorkObject(n)# 連接線程self.workobject.signal.connect(self.myprint)

myprint()函數是我自己定義的,主要是爲了將接受的信號進行打印。

一般開發GUI界面時,都會用到信號與槽,因此需要好好了解下玩法。

 

(2)多線程的實現

  # 將自己線程交於QThead類來管理  self.workthread = QThread()  self.workobject.moveToThread(self.workthread)  # 啓動線程  self.workthread.started.connect(self.workobject.run)  self.workthread.start()

  這裏就將我們自己的線程,通過moveToThread方法交於了QThread類,並由它來管理我們的線程,包括啓動線程、線程運行、線程停止等。

    另外,在自己線程運行時,如果再次運行一個新的線程,即我在點擊錄屏後再次點擊錄屏,就會報錯,錯誤內容如下:

QThread: Destroyed while thread is still running

因此如果要啓動一個新的線程,需要self.workthread.quit()。

4

示例代碼

# coding=utf-8# @Auther : "鵬哥賊優秀"# @Date : 2019/12/3# @Software : PyCharm
import sysfrom PyQt5.QtCore import *from PyQt5.QtWidgets import *import timeimport win32api,win32con
class WorkObject(QObject):    signal = pyqtSignal(str)    def __init__(self, n):        super(WorkObject, self).__init__()        self.n = n
    def run(self):        if self.n == 1:            Minimize_Window()            # Recording(1)            self.signal.emit('已選擇自定義錄屏')        elif self.n == 2:            Minimize_Window()            # Recording(2)            self.signal.emit('已選擇全屏錄屏')
def Minimize_Window():    win32api.keybd_event(91, 0, 0, 0)    time.sleep(0.5)    win32api.keybd_event(40, 0, 0, 0)    time.sleep(0.5)    win32api.keybd_event(91, 0, win32con.KEYEVENTF_KEYUP, 0)    win32api.keybd_event(40, 0, win32con.KEYEVENTF_KEYUP, 0)
class Ui_Mainwindow():    def setupUi(self, top):        # 垂直佈局類QVBoxLayout        layout = QVBoxLayout(top)        # 添加錄屏相關按鈕        button1 = QPushButton("自定義錄屏")        layout.addWidget(button1)        button2 = QPushButton("全屏錄屏")        layout.addWidget(button2)        button3 = QPushButton("停止錄屏")        layout.addWidget(button3)        self.text = QPlainTextEdit('歡迎使用!By 鵬哥賊優秀')        layout.addWidget(self.text)        button1.clicked.connect(lambda: self.work(1))        button2.clicked.connect(lambda: self.work(2))        button3.clicked.connect(self.stop)
    def work(self, n):        # 創建線程        self.workobject = WorkObject(n)        # 連接線程        self.workobject.signal.connect(self.myprint)        # 將自己線程交於QThead類來管理        self.workthread = QThread()        self.workobject.moveToThread(self.workthread)        # 啓動線程        self.workthread.started.connect(self.workobject.run)        self.workthread.start()
    def stop(self):        print('已選擇結束錄屏')        # StopRecording()        # 結束線程        self.workthread.quit()
    def myprint(self,n):        print(n)        self.text.setPlainText(n)
if __name__ == "__main__":    app = QApplication(sys.argv)    top = QWidget()    top.setWindowTitle('錄屏小工具')    top.resize(300, 170)    ui = Ui_Mainwindow()    ui.setupUi(top)    top.show()    sys.exit(app.exec_())

 

5

小技巧

這裏我還想講一些QT5編程時用到的小技巧:如何定位調試gui界面類的錯誤 ?比如如果我們的代碼有問題,在運行GUI時會出現如下現象:

但是你是無法從控制檯上看到錯誤日誌。

這裏有2個方法來解決這一問題。

A、通過cmd窗口來運行,這樣錯誤日誌會打印在cmd窗口上了;

B、在pycharm編輯運行方式時,勾選以下選項(建議使用這種方法)

 

~~~下課鈴~~~

 

點擊下方詩句,可以留言互動喔  

你有你的清歡渡,我有我的不歸路。終有弱水替滄海,再把相思寄巫山。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章