python GUI库图形界面开发之PyQt5线程类QThread详细使用方法
作者:jia666666 发布时间:2023-12-03 20:29:40
QThread是Qt的线程类中最核心的底层类。由于PyQt的的跨平台特性,QThread要隐藏所有与平台相关的代码
要使用的QThread开始一个线程,可以创建它的一个子类,然后覆盖其它QThread.run()函数
class Thread(QThread):
def __init __(self):
super(Thread,self).__ init __()
def run(self):
#线程相关的代码
pass
接下来创建一个新的线程
thread = Thread()
thread.start()
可以看出,PyQt的线程使用非常简单—-建立一个自定义的类(如thread),自我继承自QThread ,并实现其run()方法即可
在使用线程时可以直接得到Thread实例,调用其start()函数即可启动线程,线程启动之后,会自动调用其实现的run()的函数,该方法就是线程的执行函数
业务的线程任务就写在run()函数中,当run()退出之后线程就基本结束了,QThread有started和finished信号,可以为这两个信号指定槽函数,在线程启动和结束之时执行一段代码进行资源的初始化和释放操作,更灵活的使用方法是,在自定义的QThread实例中自定义信号,并将信号连接到指定的槽函数,当满足一定的业务条件时发射此信号
QThread类中的常用方法
方法 | 描述 |
---|---|
start() | 启动线程 |
wait() | 阻止线程,直到满足如下条件之一 |
与此QThread对象关联的线程已完成执行(即从run返回时),如果线程完成执行,此函数返回True,如果线程尚未启动,也返回True | |
等待时间的单位是毫秒,如果时间是ULONG_MAX(默认值·),则等待,永远不会超时(线程必须从run返回),如果等待超时,此函数将会返回False | |
sleep() | 强制当前线程睡眠多少秒 |
QThread类中的常用信号
信号 | 描述 |
---|---|
started | 在开始执行run函数之前,从相关线程发射此信号 |
finished | 当程序完成业务逻辑时,从相关线程发射此信号 |
QThread的使用方法实例
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
class MainWidget(QWidget):
def __init__(self, parent=None):
super(MainWidget, self).__init__(parent)
#设置标题
self.setWindowTitle('QThread多线程例子')
#实例化多线程对象
self.thread = Worker()
#实例化列表控件与按钮控件
self.listFile = QListWidget()
self.btnStart = QPushButton('开始')
#把控件放置在栅格布局中
layout = QGridLayout(self)
layout.addWidget(self.listFile, 0, 0, 1, 2)
layout.addWidget(self.btnStart, 1, 1)
#信号与槽函数的连接
self.btnStart.clicked.connect(self.slotStart)
self.thread.sinOut.connect(self.slotAdd)
def slotAdd(self, file_inf):
#向列表控件中添加条目
self.listFile.addItem(file_inf)
def slotStart(self):
#开始按钮不可点击,线程开始
self.btnStart.setEnabled(False)
self.thread.start()
class Worker(QThread):
sinOut = pyqtSignal(str)
def __init__(self, parent=None):
super(Worker, self).__init__(parent)
#设置工作状态与初始num数值
self.working = True
self.num = 0
def __del__(self):
#线程状态改变与线程终止
self.working = False
self.wait()
def run(self):
while self.working == True:
#获取文本
file_str = 'File index{0}'.format(self.num)
self.num += 1
# 发射信号
self.sinOut.emit(file_str)
# 线程休眠2秒
self.sleep(2)
if __name__ == '__main__':
app = QApplication(sys.argv)
demo = MainWidget()
demo.show()
sys.exit(app.exec_())
运行效果图如下
代码分析
在这个例子中,单击开始按钮,会在后台定时读取数据,并把返回的数据显示在界面中,首先使用以下代码进行布局,把列表控件和按钮控件放在栅格布局管理器中
#实例化列表控件与按钮控件
self.listFile = QListWidget()
self.btnStart = QPushButton('开始')
#把控件放置在栅格布局中
layout = QGridLayout(self)
layout.addWidget(self.listFile, 0, 0, 1, 2)
layout.addWidget(self.btnStart, 1, 1)
然后将按钮的clicked信号连接到槽函数,单击开始触发槽函数
self.btnStart.clicked.connect(self.slotStart)
def slotStart(self):
#开始按钮不可点击,线程开始
self.btnStart.setEnabled(False)
self.thread.start()
比较复杂的是线程的信号,将线程的sinOut信号连接到slotAdd()槽函数,SlotAdd()函数负责在列表控件中动态添加字符串条目
self.thread.sinOut.connect(self.slotAdd)
def slotAdd(self,file_inf):
#向列表控件中添加条目
self.listFile.addItem(file_inf)
定义一个线程类,继承自QThread,当线程启动时,执行run()函数
class Worker(QThread):
sinOut = pyqtSignal(str)
def __init__(self, parent=None):
super(Worker, self).__init__(parent)
#设置工作状态与初始num数值
self.working = True
self.num = 0
def __del__(self):
#线程状态改变与线程终止
self.working = False
self.wait()
def run(self):
while self.working == True:
#获取文本
file_str = 'File index{0}'.format(self.num)
self.num += 1
# 发射信号
self.sinOut.emit(file_str)
# 线程休眠2秒
self.sleep(2)
多线程失败案例
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
global sec
sec=0
def setTime():
global sec
sec+=1
#Led显示数字+1
lcdNumber.display(sec)
def work():
#计时器每秒计数
timer.start(1000)
for i in range(200000000):
pass
timer.stop()
if __name__ == '__main__':
app=QApplication(sys.argv)
top=QWidget()
top.resize(300,120)
#垂直布局
layout=QVBoxLayout(top)
#添加一个显示面板
lcdNumber=QLCDNumber()
layout.addWidget(lcdNumber)
button=QPushButton('测试')
layout.addWidget(button)
timer=QTimer()
#每次计时结束,触发setTime
timer.timeout.connect(setTime)
button.clicked.connect(work)
top.show()
sys.exit(app.exec_())
失败效果图如下
长时间停留在此界面,知道多线程任务完成后,此界面才会动,当耗时程序非常大时,就会造成程序运行失败的假象,实际还是在后台运行的,只是没有显示在主窗口的界面上,当然用户体验也就非常差,那么如何解决这个问题呢,下面实例三进行解答
分离UI主线程与工作线程实例
import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
global sec
sec = 0
class WorkThread(QThread):
#实例化一个信号对象
trigger = pyqtSignal()
def __int__(self):
super(WorkThread, self).__init__()
def run(self):
#开始进行循环
for i in range(2000000000):
pass
# 循环完毕后发出信号
self.trigger.emit()
def countTime():
global sec
sec += 1
# LED显示数字+1
lcdNumber.display(sec)
def work():
# 计时器每秒计数
timer.start(1000)
# 计时开始
workThread.start()
# 当获得循环完毕的信号时,停止计数
workThread.trigger.connect(timeStop)
def timeStop():
#定时器停止
timer.stop()
print("运行结束用时", lcdNumber.value())
global sec
sec = 0
if __name__ == "__main__":
app = QApplication(sys.argv)
top = QWidget()
top.resize(300, 120)
# 垂直布局类QVBoxLayout
layout = QVBoxLayout(top)
# 加显示屏,按钮到布局中
lcdNumber = QLCDNumber()
layout.addWidget(lcdNumber)
button = QPushButton("测试")
layout.addWidget(button)
#实例化定时器与多线程类
timer = QTimer()
workThread = WorkThread()
button.clicked.connect(work)
# 每次计时结束,触发 countTime
timer.timeout.connect(countTime)
top.show()
sys.exit(app.exec_())
运行效果,程序主界面的数值会每秒增加1,直到循环结束,这里就避免了主界面长时间不动的尴尬!
QThread线程事件处理实例
对于执行很耗时的程序来说,由于PyQt需要等待程序执行完毕才能进行下一步,这个过程表现在界面上就是卡顿,而如果需要执行这个耗时程序时不断的刷新界面。那么就可以使用QApplication.processEvents(),那么就可以一边执行耗时程序,一边刷新界面的功能,给人的感觉就是程序运行很流畅,因此QApplicationEvents()的使用方法就是,在主函数执行耗时操作的地方,加入QApplication.processEvents()
import sys,time
from PyQt5.QtWidgets import QWidget,QPushButton,QApplication,QListWidget,QGridLayout
class WinForm(QWidget):
def __init__(self,parent=None):
super(WinForm, self).__init__(parent)
#设置标题与布局方式
self.setWindowTitle('实时刷新界面的例子')
layout=QGridLayout()
#实例化列表控件与按钮控件
self.listFile=QListWidget()
self.btnStart=QPushButton('开始')
#添加到布局中指定位置
layout.addWidget(self.listFile,0,0,1,2)
layout.addWidget(self.btnStart,1,1)
#按钮的点击信号触发自定义的函数
self.btnStart.clicked.connect(self.slotAdd)
self.setLayout(layout)
def slotAdd(self):
for n in range(10):
#获取条目文本
str_n='File index{0}'.format(n)
#添加文本到列表控件中
self.listFile.addItem(str_n)
#实时刷新界面
QApplication.processEvents()
#睡眠一秒
time.sleep(1)
if __name__ == '__main__':
app=QApplication(sys.argv)
win=WinForm()
win.show()
sys.exit(app.exec_())
本文详细介绍了python GUI库PyQt5的线程类QThread详细使用方法,想了解更多相关知道请查看下面的相关链接
来源:https://blog.csdn.net/jia666666/article/details/81705675
猜你喜欢
- 和朋友讨论时,我提到过一个观点,所有框架层设计中,最核心的是导航设计。最近更看到有国外同行提出“80%的可用性是导航!”因为良好的导航可以保
- 在用户体验量化方法研究(一)中,我们以用户体验层次模型为基础,提出了三种量化用户体验的方法:以任务为中心、以行为为中心以及以体验为中心的量化
- 前言大家都知道Python 是一门强类型、动态类型检查的语言。所谓动态类型,是指在定义变量时,我们无需指定变量的类型,Python 解释器会
- 显示图像是 Opencv最基本的操作之一, imshow()函数可以实现该操作。如果使用过其他GUI框架背景,就会很自然地调用 imshow
- 本文只考虑模板中的字符串,不考虑字符串中带标签的情况。模板中的字符串文字不会自动转义,因为这里默认模板的作者已经正确书写模板的内容。{{ d
- 它在Lynx里也会运行得很好:<%@ Language=VBScript %><HTML><
- //获得视频文件的缩略图function getVideoCover($file,$time,$name) { &nb
- 适配竖屏横向尺度,禁止出现横向滚屏常规QVGA机型竖屏状态下,14号字体,单行仅显示13.5个字。资讯频道的新闻短标题要控制在13字以内才能
- 方法一: $(document).on('touchmove',function(e){ e.preventDefault(
- 最近,随着数据库的日益庞大,本来两个差不多的数据库,我开始发现我的数据库查询起来越来越比我朋友网站的慢了,经过初步对照,问题好像出在访问记录
- 如果能,请问如何实现 谢谢set aa=server.cre
- 代码如下:--根据MAX(MIN)ID CREATE PROC [dbo].[proc_select_id] @pageindex int=
- 1. composer 安装 PDF组件composer require setasign/fpdicomposer require set
- 今天在 经纬 同学blog看到的。有这么一段代码:<ul id="demo"><li>
- 用户管理是绝大部分Web网站都需要解决的问题。用户管理涉及到用户注册和登录。用户注册相对简单,我们可以先通过API把用户注册这个功能实现了:
- 代码如下:CREATE PROCEDURE page @tblName varchar(255), -- 表名 @strGetF
- 本文实例讲述了Python使用Selenium模块模拟浏览器抓取斗鱼直播间信息。分享给大家供大家参考,具体如下:import timefro
- python实现的五子棋,能够自动判断输赢,没有是实现电脑对战功能源码下载:pygame五子棋# 1、引入pygame 和 pygame.l
- MySQL从5.1开始支持event功能,类似oracle的job功能。有了这个功能之后我们就可以让MySQL自动的执行数据汇总等功能,不用
- PJBLOG3的相关日志,现在网上好像还没有谁有相关的修改说明吧,反正升级之后,正好有必要,也就写了个,在这里也给大家共享共享。当前相关日志