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

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

目录

1、QTimer计时器类


2、QThread多线程类


3、事件处理类


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


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


1、QTimer计时器类

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


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


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


image.png


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


image.png


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



image.png



示例中,初始化一个定时器,把定时器的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类中的常用方法如下表所示:


image.png


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


image.png


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


image.png


示例中,在主界面中有一个用于显示时间的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()。


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


image.png


实现代码如下所示:


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

文章知识点与官方知识档案匹配,可进一步学习相关知识


相关文章
|
2月前
|
数据采集 存储 JSON
Python爬取知乎评论:多线程与异步爬虫的性能优化
Python爬取知乎评论:多线程与异步爬虫的性能优化
|
2月前
|
人工智能 安全 调度
Python并发编程之线程同步详解
并发编程在Python中至关重要,线程同步确保多线程程序正确运行。本文详解线程同步机制,包括互斥锁、信号量、事件、条件变量和队列,探讨全局解释器锁(GIL)的影响及解决线程同步问题的最佳实践,如避免全局变量、使用线程安全数据结构、精细化锁的使用等。通过示例代码帮助开发者理解并提升多线程程序的性能与可靠性。
110 0
|
2月前
|
数据采集 监控 调度
干货分享“用 多线程 爬取数据”:单线程 + 协程的效率反超 3 倍,这才是 Python 异步的正确打开方式
在 Python 爬虫中,多线程因 GIL 和切换开销效率低下,而协程通过用户态调度实现高并发,大幅提升爬取效率。本文详解协程原理、实战对比多线程性能,并提供最佳实践,助你掌握异步爬虫核心技术。
|
3月前
|
JSON 算法 Java
打造终端里的下载利器:Python实现可恢复式多线程下载器
在数字时代,大文件下载已成为日常需求。本文教你用Python打造专业级下载器,支持断点续传、多线程加速、速度限制等功能,显著提升终端下载体验。内容涵盖智能续传、多线程分块下载、限速控制及Rich库构建现代终端界面,助你从零构建高效下载工具。
232 1
|
2月前
|
数据采集 存储 Java
多线程Python爬虫:加速大规模学术文献采集
多线程Python爬虫:加速大规模学术文献采集
|
3月前
|
数据采集 网络协议 前端开发
Python多线程爬虫模板:从原理到实战的完整指南
多线程爬虫通过并发请求大幅提升数据采集效率,适用于大规模网页抓取。本文详解其原理与实现,涵盖任务队列、线程池、会话保持、异常处理、反爬对抗等核心技术,并提供可扩展的Python模板代码,助力高效稳定的数据采集实践。
163 0
|
数据安全/隐私保护 C++ 计算机视觉
Qt(C++)开发一款图片防盗用水印制作小工具
文本水印是一种常用的防盗用手段,可以将文本信息嵌入到图片、视频等文件中,用于识别和证明文件的版权归属。在数字化和网络化的时代,大量的原创作品容易被不法分子盗用或侵犯版权,因此加入文本水印成为了保护原创作品和维护知识产权的必要手段。 通常情况下,文本水印可以包含版权声明、制作者姓名、日期、网址等信息,以帮助识别文件的来源和版权归属。同时,为了增强防盗用效果,文本水印通常会采用字体、颜色、角度等多种组合方式,使得水印难以被删除或篡改,有效地降低了盗用意愿和风险。 开发人员可以使用图像处理技术和编程语言实现文本水印的功能,例如使用Qt的QPainter类进行文本绘制操作,将文本信息嵌入到图片中,
416 1
Qt(C++)开发一款图片防盗用水印制作小工具
|
监控 C++ 容器
【qt】MDI多文档界面开发
【qt】MDI多文档界面开发
485 0

推荐镜像

更多