Python Qt GUI设计:QTimer计时器类、QThread多线程类和事件处理类(基础篇—8)

Python Qt GUI设计:QTimer计时器类、QThread多线程类和事件处理类(基础篇—8)一般来说,多线程技术涉及三种方法,其中第一种是使用计时器模块QTimer;第二种是使用多线程模块QThread;最后是使用事件处理的功能。

大家好,又见面了,我是你们的朋友全栈君。

目录

1、QTimer计时器类

2、QThread多线程类

3、事件处理类


一般情况下,应用程序都是单线程运行的,但是对于GUI程序来说,单线程有时候满足不了需求。例如,如果需要执行一个特别耗时的操作,在执行过程中整个程序就会卡顿,效果就非常不理想或者Windows系统也认为程序运行出错,自动关闭了程序。要解决这种问题就涉及多线程的知识。

一般来说,多线程技术涉及三种方法,其中第一种是使用计时器模块QTimer;第二种是使用多线程模块QThread;最后是使用事件处理的功能。

1、QTimer计时器类

如果要在应用程序中周期性地进行某项操作,比如周期性地检测主机的CPU值,则需要用到QTimer(定时器),QTimer类提供了重复的和单次的定时器。要使用定时器,需要先创建一个QTimer实例,将其timeout信号连接到相应的槽,并调用start()。然后,定时器会以恒定的间隔发出timeout信号。

当窗口控件收到timeout信号后,它就会停止这个定时器。这是在图形用户界面中实现复杂工作的一个典型方法,随着技术的进步,多线程在越来越多的平台上被使用,最终QTimer对象会被线程所替代。

QTimer类中的常用方法如下表所示:

Python Qt GUI设计:QTimer计时器类、QThread多线程类和事件处理类(基础篇—8)

QTimer类中的常用信号如下表所示: 

Python Qt GUI设计:QTimer计时器类、QThread多线程类和事件处理类(基础篇—8)

通过一个示例,了解QTimer计时器类的使用方法,效果如下所示:

Python Qt GUI设计:QTimer计时器类、QThread多线程类和事件处理类(基础篇—8)

Python Qt GUI设计:QTimer计时器类、QThread多线程类和事件处理类(基础篇—8)

示例中,初始化一个定时器,把定时器的timeout信号与showTime()槽函数连接起来。使用连接的槽函数显示当前时间,并在标签上显示系统现在的时间。单击“开始”按钮,启动定时器,并使”开始”按钮失效。单击“结束”按钮,停止定时器,并使“结束”按钮失效。

实现代码如下所示:

from PyQt5.QtWidgets import QWidget,  QPushButton ,  QApplication ,QListWidget,  QGridLayout , QLabel
from PyQt5.QtCore import QTimer ,QDateTime
import sys 

class WinForm(QWidget):  
	
	def __init__(self,parent=None): 
		super(WinForm,self).__init__(parent) 
		self.setWindowTitle("QTimer demo")
		self.listFile= QListWidget() 
		self.label = QLabel('显示当前时间')
		self.startBtn = QPushButton('开始') 
		self.endBtn = QPushButton('结束') 
		layout = QGridLayout(self) 

        # 初始化一个定时器
		self.timer = QTimer(self)
        # showTime()方法
		self.timer.timeout.connect(self.showTime)
		
		layout.addWidget(self.label,0,0,1,2)   
		layout.addWidget(self.startBtn,1,0) 
		layout.addWidget(self.endBtn,1,1) 		
		
		self.startBtn.clicked.connect( self.startTimer) 
		self.endBtn.clicked.connect( self.endTimer) 
				
		self.setLayout(layout)   
		
	def showTime(self): 
		# 获取系统现在的时间
		time = QDateTime.currentDateTime() 
		# 设置系统时间显示格式
		timeDisplay = time.toString("yyyy-MM-dd hh:mm:ss dddd");
		# 在标签上显示时间
		self.label.setText( timeDisplay ) 

	def startTimer(self): 
        # 设置计时间隔并启动
		self.timer.start(1000)
		self.startBtn.setEnabled(False)
		self.endBtn.setEnabled(True)

	def endTimer(self): 
		self.timer.stop()
		self.startBtn.setEnabled(True)
		self.endBtn.setEnabled(False)
		
if __name__ == "__main__":  
	app = QApplication(sys.argv)  
	form = WinForm()  
	form.show()  
	sys.exit(app.exec_())

2、QThread多线程类

QThread是Qt线程类中最核心的底层类,由于PyQt的跨平台特性,QThread要隐藏所有与平台相关的代码。

在使用线程时可以直接得到Thread实例,调用其start()函数即可启动线程。线程启动之后,会自动调用其实现的run方法,该方法就是线程的执行函数。

业务的线程任务就写在run()函数中,当run()退出之后线程基本就结束了。QThread有started和finished信号,可以为这两个信号指定槽函数,在线程启动和结束时执行一段代码进行资源的初始化和释放操作。更灵活的使用方法是,在自定义的QThread实例中自定义信号,并将信号连接到指定的槽函数,当满足一定的业务条件后发射此信号。

QThread类中的常用方法如下表所示:

Python Qt GUI设计:QTimer计时器类、QThread多线程类和事件处理类(基础篇—8)

QThread类中的常用信号如下表所示: 

Python Qt GUI设计:QTimer计时器类、QThread多线程类和事件处理类(基础篇—8)

通过一个示例,了解QThread多线程类的使用方法,效果如下所示:

Python Qt GUI设计:QTimer计时器类、QThread多线程类和事件处理类(基础篇—8)

示例中,在主界面中有一个用于显示时间的LCD数字面板,还有一个用于启动任务的按钮。用户单击”测试”按钮后,将开始一次非常耗时的计算(在程序中用一个2000 000 000次的循环来模拟这次非常耗时的工作,在真实的程序中可能是一个网络下载操作,从网络上下载一个很大的视频文件),同时LCD数字面板开始显示所用的毫秒数,并通过一个计时器进行更新。但是单击”测试“按钮后可见窗口卡死无法操作。此时在PyQt中所有的窗口都在UI主线程中(就是执行了QApplication.exec()的线程),在这个线程中执行耗时的操作会阻塞UI线程,从而让窗口停止响应。如果窗口长时间没有响应,则会影响用户体验,更严重的会导致程序崩溃。所以,为了避免出现这样的问题,要使用QThread开启一个新的线程,在这个线程中完成耗时的操作。

实现代码如下所示:

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_())

3、事件处理类

PyQt为事件处理提供了两种机制:高级的信号与槽机制以及低级的事件处理程序。本篇文博只介绍低级的事件处理程序即:processEvents()函数的使用方法,它的作用是处理事件,简单地说,就是刷新页面。

对于执行很耗时的程序来说,由于PyQt需要等待程序执行完毕才能进行下一步,这个过程表现在界面上就是卡顿。而如果在执行这个耗时程序时不断地运行
QApplication.processEvents(),那么就可以实现一边执行耗时程序,一边刷新页面的功能,给人的感觉就是程序运行很流畅。

因此QApplication.processEvents()的使用方法就是,在主函数执行耗时操作的地方,加入QApplication.processEvents()。

通过一个示例,了解事件处理类的使用方法,效果如下所示:

Python Qt GUI设计:QTimer计时器类、QThread多线程类和事件处理类(基础篇—8)

实现代码如下所示:

from PyQt5.QtWidgets import QWidget,  QPushButton ,  QApplication ,QListWidget,  QGridLayout 
import sys 
import time

class WinForm(QWidget):  
	
	def __init__(self,parent=None): 
		super(WinForm,self).__init__(parent) 
		self.setWindowTitle("实时刷新界面例子")        
		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.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)  
	form = WinForm()  
	form.show()  
	sys.exit(app.exec_())
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/140212.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • airplay影像_播放ftp服务器的视频

    airplay影像_播放ftp服务器的视频http://bbs.weiphone.com/read-htm-tid-1785042.htmliOS客户端软件:AirPlayer[支持RMVB,MKV,MP4,AVI等等格式],另外有个PulgPlayer不支持RMVBMKV等等格式。PC端媒体服务器:WIN7自带的媒体中心(论坛有设置方法的教程,这不介绍了)…

    2025年12月6日
    6
  • Python学习总结之基础语法知识汇总(一)

    Python学习总结之基础语法知识汇总(一)本文章包含了Python一系列基本知识,其中包括:基本数据类型(整数,浮点数,复数,字符串);分支语句;异常处理;函数;局部变量与全局变量;递归;组合数据类型(集合,元组,列表,字典);文件基本操作基本数据类型一,数字类型及操作(1)整数类型可正可负,无取值范围限制pow(x,y):计算x^y(2)浮点数类型存在不确定尾数 rou…

    2022年6月24日
    44
  • WPA2协议新攻击方法(KRACK)—WPA2密钥重安装漏洞[通俗易懂]

    WPA2协议新攻击方法(KRACK)—WPA2密钥重安装漏洞[通俗易懂]KeyReinstallationAttacksBreakingWPA2byforcingnoncereuse今年9月份CCS公布了一篇新论文,该论文提出了一种新的攻击方法:KeyReinstallationAttacks,这种攻击方法对WPA2危害甚大。本文简单介绍该攻击方法。我们都知道所有WiFi网络都是靠WiFiProtectedAccess协议的某个实现版

    2022年6月10日
    44
  • 服务熔断与服务降级详解

    服务熔断与服务降级详解为深入理解服务雪崩解决方案中服务熔断和服务降级两个方式,在这儿做一个详解服务熔断什么是服务熔断:当下游的服务因为某种原因突然变得不可用或响应过慢,上游服务为了保证自己整体服务的可用性,不再继续调用目标服务,直接返回,快速释放资源。如果目标服务情况好转则恢复调用服务熔断的原理:业内普遍采用断路器模式原理:当远程服务被调用时,断路器将监视这个调用,如调用时间太长,断路器将会介入并中断调用。此外,断路器将监视所有对远程资源的调用,如对某一个远程资源的调用失败次数足够多,那么断路器

    2022年10月20日
    3
  • 计算距离矩阵的方法_矩阵的欧式距离

    计算距离矩阵的方法_矩阵的欧式距离给定一个 N 行 M 列的 01 矩阵 A,A[i][j] 与 A[k][l] 之间的曼哈顿距离定义为:dist(A[i][j],A[k][l])=|i−k|+|j−l|输出一个 N 行 M 列的整数矩阵 B,其中:B[i][j]=min1≤x≤N,1≤y≤M,A[x][y]=1dist(A[i][j],A[x][y])输入格式第一行两个整数 N,M。接下来一个 N 行 M 列的 01 矩阵,数字之间没有空格。输出格式一个 N 行 M 列的矩阵 B,相邻两个整数之间用一个空格隔开。数据范围

    2022年8月8日
    8
  • SpringBoot2-[SpringBoot优缺点、微服务理解、版本仲裁]

    SpringBoot2-[SpringBoot优缺点、微服务理解、版本仲裁]??‍?博主介绍:大家好,我是芝士味的椒盐,一名在校大学生,热爱分享知识,很高兴在这里认识大家??擅长领域:Java、大数据、运维、电子??如果本文章各位小伙伴们有帮助的话,?关注+??点赞+?评论+?收藏,相应的有空了我也会回访,互助!!!?另本人水平有限,旨在创作简单易懂的文章,在文章描述时如有错,恳请各位大佬指正,在此感谢!!!文章目录Spring.ioSpring5重大升级SpringBoot优点SpringBoot缺点微服务SpringBoot官方文档Maven设置SpringBo..

    2022年9月26日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号