PyQt5 笔记4 – 多线程
1、多线程
QT 程序的设计应该遵循UI线程与工作线程分离的原则,否则可能会因为工作线程运行时间太久造成程序未响应问题。如果程序有多个功能要同步执行,也必须另开线程执行。
QT 多线程的使用主要是通过 QThread 来实现。有两种方法:一种是创建一个继承自QThread的类并重写它的run()方法;另一种是,创建类,实例化对象并转换为线程对象。
2、重写QThread的run()方法
创建一个继承自QThread的类并重写它的run()方法
# 创建视频播放的线程类:
class Thread(QThread):
# 自定义信号
show_signal = pyqtSignal(QImage)
# 构造函数,接受参数
def __init__(self, file_name, browser):
QThread.__init__(self)
self.video_name = file_name
self.browser = browser
# 重写run()方法
def run(self):
# 实例化一个读取视频对象
cap = cv2.VideoCapture(self.video_name)
while cap.isOpened():
# 读取视频帧
ret, frame = cap.read()
# 获取视频的帧数
fps = cap.get(cv2.CAP_PROP_FPS)
if ret:
# 转换图片格式
rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
qt_image = QImage(rgb_image.data, rgb_image.shape[1], rgb_image.shape[0], QImage.Format_RGB888)
p = qt_image.scaled(640, 480, Qt.KeepAspectRatio)
# 发射信号
self.show_signal.emit(p)
time.sleep(1/fps)
else:
image = QImage('E:/11.jpg')
self.browser.ui.lb_show.setPixmap(QPixmap.fromImage(image))
self.browser.ui.lb_show.adjustSize()
print('播放结束')
break
使用创建的线程
# 实例化线程对象,并传入参数。
th = Thread(file_name, self)
# 绑定信号与槽
th.show_signal.connect(self.show_image)
# 开启线程
th.start()
# 等待线程结束。括号内可填写等待时间。
# th.wait()
# 关闭线程
# th.quit()
node: 如果是在函数中实例化线程对象,要实例化为全局对象或者类对象,要不然函数结束后会销毁资源,导致程序崩溃。
3、工作对象转换为线程对象
创建一个继承自QObject的类并写一个想要运行的函数
class Worker(QObject):
def __init__(self, parent=None):
super(Worker, self).__init__(parent)
def work(self):
print('当前线程: %s' % hex(int(QThread.currentThreadId())))
实例化工作对象并转换为线程对象
# 查看当前线程id
print('主线程: %s' % hex(int(QThread.currentThreadId())))
# 实例化线程对象
t = QThread()
# 实例化工作类对象
worker = Worker()
# 工作类对象转化为线程对象
worker.moveToThread(t)
# 绑定线程启动信号的槽函数
t.started.connect(worker.work)
# 启动线程
t.start()
node: 如果不是通过启动线程调用worker.work,而是直接调用worker.work这样是不会开启新线程的。