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类中的常用方法
QThread类中的常用信号
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详细使用方法,想了解更多相关知道请查看下面的相关链接
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 【雨果唱片】中国管弦乐《鹿回头》WAV
- APM亚流新世代《一起冒险》[FLAC/分轨][106.77MB]
- 崔健《飞狗》律冻文化[WAV+CUE][1.1G]
- 罗志祥《舞状元 (Explicit)》[320K/MP3][66.77MB]
- 尤雅.1997-幽雅精粹2CD【南方】【WAV+CUE】
- 张惠妹.2007-STAR(引进版)【EMI百代】【WAV+CUE】
- 群星.2008-LOVE情歌集VOL.8【正东】【WAV+CUE】
- 罗志祥《舞状元 (Explicit)》[FLAC/分轨][360.76MB]
- Tank《我不伟大,至少我能改变我。》[320K/MP3][160.41MB]
- Tank《我不伟大,至少我能改变我。》[FLAC/分轨][236.89MB]
- CD圣经推荐-夏韶声《谙2》SACD-ISO
- 钟镇涛-《百分百钟镇涛》首批限量版SACD-ISO
- 群星《继续微笑致敬许冠杰》[低速原抓WAV+CUE]
- 潘秀琼.2003-国语难忘金曲珍藏集【皇星全音】【WAV+CUE】
- 林东松.1997-2039玫瑰事件【宝丽金】【WAV+CUE】