【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编辑运行方式时,勾选以下选项(建议使用这种方法)

 

~~~下课铃~~~

 

点击下方诗句,可以留言互动喔  

你有你的清欢渡,我有我的不归路。终有弱水替沧海,再把相思寄巫山。

 

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