哈喽大家好,我是鹏哥。
今天我们把上周录屏小工具的一些细节进行详细说明下,因此这次的主题是 —— QThread的正确使用。
1
写在前面
我们先回顾下上次博客是如何实现pyqt5的多线程功能的?
class WorkThread(QThread):def __init__(self, n):super(WorkThread, self).__init__()self.n = ndef 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 : PyCharmimport sysfrom PyQt5.QtCore import *from PyQt5.QtWidgets import *import timeimport win32api,win32conclass WorkObject(QObject):signal = pyqtSignal(str)def __init__(self, n):super(WorkObject, self).__init__()self.n = ndef 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):# 垂直布局类QVBoxLayoutlayout = 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编辑运行方式时,勾选以下选项(建议使用这种方法):

~~~下课铃~~~


点击下方诗句,可以留言互动喔
你有你的清欢渡,我有我的不归路。终有弱水替沧海,再把相思寄巫山。

本文详细介绍了如何在PyQt5中科学地使用QThread进行多线程操作,避免直接在QThread类中放置业务逻辑。通过moveToThread方法和信号与槽机制,实现了GUI界面与工作线程的有效分离,确保了界面响应性和线程安全性。
--moveToThread方法的使用&spm=1001.2101.3001.5002&articleId=103396046&d=1&t=3&u=f205c7429e7844c7854650ab36d03149)
9521

被折叠的 条评论
为什么被折叠?



