多线程以及在PYQT中的使用

1.多线程

简单来说就是可以用多线程同时执行多个程序。

在python中,我们用的是

threading库

这个库包含了线程的方法和其他配套方法(比如锁)。似乎 concurrent库会更方便更安全,下次可以试一下并介绍它的用法。

 

一般threading库记住下面的就够用了。

创建线程

 

 

注意:kwargs传参要求用{},key和函数参数名对应。

用args传参记住用(),如果参数只有一个,最后要加一个,。 

用start()启动线程,不要用run()。run()只是运行线程内的函数,没有新开线程,相当于是在主线程中运行。start()是新开一个线程在这个线程中运行函数。

设置守护线程

 何为守护线程:当线程被设置为守护线程后,会在主线程结束时同时结束,不管线程是否执行完。

 

设置主线程阻塞到子线程执行完

可以设置timeout,单位为秒。表示等待多久后就不等了。

线程锁

python的多线程是共享全局变量的。一个变量在多个线程中都可以访问。(相应的进程里每个进程就独享它自己的全局变量了)

锁在名义上是锁的资源,但实际上是锁的一段代码,通过这段代码来锁住对资源的修改。

(对资源的访问是不会引发冲突的,两个线程同时访问一个变量不会报错,怕的是在一个线程打算输出变量值的时候,这个变量被另一个线程给改了,导致输出的值出错,事实上这种冲突永远不会导致报错)

这里介绍最简单的锁Lock。

 

记住一定要在加锁后解锁,程序可能报错导致没有解锁,可以用try...finally..来让他一定解锁。 

2.PYQT

python的一个前端UI工具,写的很完美,但是存在一些特殊情况会出现的bug,毕竟工具也是人写的,不存在真正的完美。多线程在PYQT中的运用方式正是为了这些bug而写。

3.多线程在PYQT编写的UI中的应用

在PYQT中时间处理循环会强制占用主线程。这就导致当你想跑一个复杂的逻辑的时候,主线程会被占用导致QT界面一直未响应,所以一些复杂的耗时的逻辑必须放到线程中跑。

这里再说一个小技巧。比如按下一个按钮跑一个逻辑时,注意一定要把整个逻辑放到线程中,按钮触发的事件就是启动线程。不要出现这种情况,触发的事件还是一个这个逻辑,不过是把这个逻辑中的一些流程拆下来放到线程中执行,这样UI还是会卡住(当然这个不一定,但是对笔者所在的集成测试领域来说是这样的)。

PYQT要求显示操作(显示操作包括在界面上显示数据或者画图)必须在主线程中完成,所以当你把显示操作放到子线程中时,有可能会出现冲突并报错。(普通的显示可能不会触发报错,但耗时的显示操作(如画图)确实会报错)。

当然某些情况你必须把显示放到子线程中,这时候就要用到PYQT的信号与槽机制。

自定义一个信号,信号连接的是显示的函数,你在线程中想显示时就触发信号。这样就能规避这个问题。

有可能你设置显示值后界面不会立即显示,必须点击一下UI才会显示或改变。这时有两种选择,一是使用

QApplication.processEvents()

强制刷新整个界面,二是用控件.repaint()重新绘制。ps:这两个方法好像都有问题,可能会引发程序的不报错闪退。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
PyQt使用多线程处理视频需要注意以下几个步骤: 1. 导入PyQt的和QtGui模块以OpenCV模块。 ```python from PyQt5.QtCore import Qt, QThread, pyqtSignal from PyQt5.QtGui import QImage, QPixmap import cv2 ``` 2. 创建一个继承自QThread的线程类,用于视频处理。在run()方法打开视频文件并进行处理。 ```python class VideoThread(QThread): change_pixmap_signal = pyqtSignal(QImage) def run(self): cap = cv2.VideoCapture('video.mp4') while cap.isOpened(): ret, frame = cap.read() if ret: rgb_image = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) h, w, ch = rgb_image.shape bytes_per_line = ch * w convert_to_qt_format = QImage(rgb_image.data, w, h, bytes_per_line, QImage.Format_RGB888) p = convert_to_qt_format.scaled(640, 480, Qt.KeepAspectRatio) self.change_pixmap_signal.emit(p) else: break cap.release() ``` 3. 在主窗口类创建一个显示视频的QLabel,并将其放置在布局。在构造方法创建VideoThread的实例并连接其change_pixmap_signal信号到更新QLabel的槽函数。 ```python class MainWindow(QWidget): def __init__(self): super().__init__() self.label = QLabel(self) self.label.setAlignment(Qt.AlignCenter) self.label.setMinimumSize(1, 1) vbox = QVBoxLayout() vbox.addWidget(self.label) self.setLayout(vbox) self.thread = VideoThread(self) self.thread.change_pixmap_signal.connect(self.update_image) self.thread.start() def update_image(self, pixmap): self.label.setPixmap(pixmap) ``` 4. 最后,在主程序创建QApplication实例并显示主窗口。 ```python if __name__ == '__main__': app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec_()) ``` 注意:在多线程访问Qt GUI元素时应保证线程安全。在上面的例子,我们使用了信号槽机制来更新QLabel的图像显示。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值