python GUI库图形界面开发之PyQt5线程类QThread详细使用方法

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详细使用方法,想了解更多相关知道请查看下面的相关链接

(0)

相关推荐

  • python GUI库图形界面开发之PyQt5开发环境配置与基础使用

    PyQt5安装 在cmd下输入 pip install PyQt5 完成PyQt5安装,再安装qt designer,可以使用pip安装 pip install PyQt5-tools 安装完成后,在python安装目录下可以看到 配置PyCharm 配置PyCharm是为了在Pycharm里面实现打开qt designer,然后生成qt文件,然后将qt文件转换成python语言的软件文件. 打开Pycharm,按下图操作 打开Extrernal Tools之后,点击上如绿色的+,添加Tools

  • Python GUI库PyQt5样式QSS子控件介绍

    QSS子控件 QSS子控件实际上也是一种选择器,其应用在一些复合控件上,典型的如QComboBox,该控件的外观是,有一个矩形的外边框,右边有一个下拉箭头,点击之后会弹出下拉列表,例如: QComboBox:drop-down {image:url(dropdown.png)} 上面的样式指定所有的QComboBox下拉箭头的图片是自定义的,图片文件为dropdown.png ::drop-down子控件选择器可以与上面提到到的选择器一起联合使用,例如 QComboBox#myQComboBox

  • python图形开发GUI库pyqt5的详细使用方法及各控件的属性与方法

    本文主要列出来python图形开发GUI库pyqt5的窗体,控件属性与方法如果你想看看python图形开发GUI库pyqt5的基础使用方法可以查看我们的另一篇文章 python图形开发GUI库pyqt5的基本使用方法详解 基本框架 import sys from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5.QtWidgets import * class Demo(QWidget): def __init__(self):

  • python如何通过pyqt5实现进度条

    这篇文章主要介绍了python如何通过pyqt5实现进度条,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 python太博大精深了,使用场景非常多.最近笔者一直使用PyQt5编一些小程序,顺便就把一些常用的东西列出来,做个记录和积累吧. 进度条是非常常用的东西,今天用的时候,顺便温习了一下,这个东西自己感觉没啥可讲的,最好的办法就是例子来说明:下面给一个简单的例子. 基本进度条使用: 进度条的函数如下: self.pbar = QProgres

  • python GUI库图形界面开发之PyQt5窗口背景与不规则窗口实例

    窗口背景主要包括,背景色与背景图片,设置窗口背景有三种方法 使用QSS设置窗口背景 使用QPalette设置窗口背景 实现PainEvent,使用QPainter绘制背景 QSS设置窗口背景 在QSS中,我们可以使用Background或者background-color的方式来设置背景色,设置窗口背景色之后,子控件默认会继承父窗口的背景色,如果想要为控件设置背景图片或图标,则可以使用setPixmap或则setIcon来完成.关于这两个函数的用法,可以参考本博客下的PyQt5的基础控件分栏 实

  • python GUI库图形界面开发之PyQt5拖放控件实例详解

    本篇,我们学习PyQt5界面中拖放(Drag 和Drop)控件. 拖放动作 在GUI中,拖放指的是点击一个对象,并将其拖动到另一个对象上的动作.比如百度云PC客户端支持的拖放文件以快速移动文件: 拖放动作能够很直观很方便的在GUI程序中完成一些很复杂或繁琐的操作. 在PyQt中实现拖放 在PyQt5中,我们也可以很轻松地使用拖放功能. 使用Qt设计师或者使用API都可以实现.我们先使用Qt设计师将GUI的图形设计出来,在之前的GUI的基础上,我们新建一个选项卡. 我们新建了一个选项卡,然后在里面

  • python GUI库图形界面开发之PyQt5信号与槽基本操作

    信号与槽基本操作 进入Qt Designer,加入控件,本文以按钮为例. 按F4开始后,选择需要加入信号与槽的按钮,如下图所示该按钮会变红,按住鼠标拉出一条红线,若该按钮需控制旁边的label,则红线连接到label上(图1),若对框体(MainWindow)进行操作,则链接到框体上,会出现一个像物理中"地线"似的符号(图2). 图1 图2 连接后,会弹出如下窗体(图3),左侧界面选择信号,如下图中选择"clicked()"代表点击按钮触发右侧对应槽的操作. 勾选下

  • python GUI库图形界面开发之PyQt5控件QTableWidget详细使用方法与属性

    QTableWidget介绍 QTableWidget是Qt程序中常用的显示数据表格的控件,类似于c#中的DataGrid.QTableWidget是QTableView的子类,它使用标准的数据模型,并且其单元数据是通过QTableWidgetItem对象来实现的,使用QTableWidget时就需要QTableWidgetItem.用来表示表格中的一个单元格,整个表格就是用各个单元格构建起来的 QTableWidget类中的常用方法 方法 描述 setROwCount(int row) 设置Q

  • Pycharm+Python+PyQt5使用详解

    1,打开cmd安装PyQt5 pip install pyqt5 2,PyQt5不再提供Qt Designer等工具,所以需要再安装pyqt5-tools pip install pyqt5-tools 3,打开Pycharm,进入设置,添加外部工具 4,添加QtDesigner,exe的路径在安装目录下C:\Program Files\Python35\Lib\site-packages\pyqt5-tools\designer.exe 5,设置"PyUIC"-- 这个主要是用来将

  • python图形开发GUI库pyqt5的基本使用方法详解

    一:安装PyQt5 pip install pyqt5 如果你的系统没有安装pip请阅读我们的另一篇文章 windows下python安装pip方法详解 二:PyQt5简单使用 #!/usr/bin/python3 # -*- coding: utf-8 -*- """ Py40.com PyQt5 tutorial In this example, we create a simple window in PyQt5. author: Jan Bodnar website:

  • Python3和pyqt5实现控件数据动态显示方式

    最近笔者在做一个pyqt5的界面,由于在日常生活中,一些实际运用的场合都需要对数据进行实时的刷新,例如对某个数值的监控,水温,室温的监控等等,都需要实时的刷新控件显示的数据. 对于实现这样的一种功能,pyqt5在面板生成的同时就固定住了UI中的数据,例如我们产生一个QLineEdit控件,然后布局在面板上,但是控件中的数据是固定的,如果这个数据是实时更新的,想要改变空间中的数据时,就要去刷新面板,pyqt5提供了一个QApplication.processEvents()的命令来刷新整个面板,但

  • python GUI库图形界面开发之PyQt5动态加载QSS样式文件

    在Qt中经常需要使用样式,为了降低耦合性(与逻辑代码分离),我们通常会定义一个QSS文件,然后编写各种控件(QLabel,QLIneEdit,QPushButton等)的样式,最后使用QApplication或QMainWindow来加载样式,这样就可以让整个应用程序共享一种样式了 编写QSS 首先新建一个扩展名为.qss的文件,如style.qss,然后将其加入资源文件(.qrc)中,在style.qss文件中编写样式代码,例如 QMainWindow{ border-image:url(./

  • python GUI库图形界面开发之PyQt5美化窗体与控件(异形窗体)实例

    在默认情况下,我们使用PyQt5创建出来的窗口和部件都是默认的样式,虽然谈不上很丑,但是也毫无美感可言.其实,在PyQt5中,我们可以有较高的自由度来自定义窗口和各种小部件的样式,通过自定义这些样式,以达到美化图形界面的目的. 本篇文章中,我们就通过一个实际的例子,使用QSS和PyQt5的配置属性,实现图形用户界面的美化工作. 首先上效果图: 一.对界面进行布局和组件的布置 在图像界面编程中,一个好的布局有助于全局把控界面的形态,而在PyQt5中,有多种布局的方式供我们选择,比较常用的布局有以下

  • python GUI库图形界面开发之PyQt5浏览器控件QWebEngineView详细使用方法

    PyQt5浏览器控件QWebEngineView PyQt5使用QWebEngineView控件来展示HTML页面,对老版本的QWebView类不在进行维护,因为QWebEngineView使用CHromium内核可以给用户带来更好的体验 QWebEngineView类中常用方法 方法 描述 load(QUrl url) 加载指定的URL并显示 setHtml(QString&html) 将网页视图的内容设置为指定的HTML内容 QWebEngineView控件使用load()函数加载一个Web

  • python GUI库图形界面开发之PyQt5信号与槽机制、自定义信号基础介绍

    信号和槽机制是 QT 的核心机制,要精通 QT 编程就必须对信号和槽有所了解.信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要地方. 在linux.windows等 GUI 工具包中,GUI组件都会注册回调函数用于处理组件所触发的动作,通常是注册对应的函数的函数指针.在之前关于Button的文章中提到了信号与槽的机制的使用,通过该机制可以很好的将组件的信号(如button的clocked.toggled.pressed等)和处理该信号的槽关

  • 浅谈PyQt5中异步刷新UI和Python多线程总结

    目前任务需要做一个界面程序,PyQt是非常方便的选择,QT丰富的控件以及python方便的编程.近期遇到界面中执行一些后台任务时界面卡死的情况,解决了在这里记录下. PyQt PyQt简介 PyQt是Qt的python接口,PyQt的文档较少,但接口和函数可以完全参照Qt,继承了Qt中大量的控件以及信号机制,十分方便.以下简介一个基本的PyQt程序. - 需要导入的类主要来自三个包 - from PyQt5.QtWidgets import 常用的控件 - PyQt5.QtCore 核心功能类,

  • Python使用PyQt5/PySide2编写一个极简的音乐播放器功能

    疫情肆虐,憋在家实在无聊,索性写点东西,于是就有了这个极极极极极简的音乐播放器. 这个极极极简的音乐播放器类似于"阅后即焚"的软件,播放器可以随机播放歌曲,获取下一首歌曲,不能重新播放上一首歌曲,不能获取歌曲的名称和演唱者.听过的歌曲,就像过眼云烟,放完即散. 下面来看看如何用Python实现这个音乐播放器软件吧! 一.创建UI界面 首先,我们来创建这个播放器的UI界面.这个播放器一共有6个控件: 左上角的程序关闭按钮: 左侧的播放状态标签: 顶部的slogan; 播放/暂停按钮: 下

  • Python GUI库PyQt5图形和特效样式QSS介绍

    QSS介绍前言 QSS即Qt样式表,是用来自定义控件外观的一种机制,QSS大量参考了Css的内容,但QSS的功能要比Css弱得多,体现在选择器少,可以使用的QSS属性也少,而且并不是所有的属性都可以应用在PyQt的控件上,QSS使页面美化跟代码层分开,利于维护 QSS的语法规则 QSS的语法规则几乎与CSS相同,QSS样式由两部分组成,其中一部分是选择器(Selector),指定哪些软件会受到影响,另一部分是声明(Declaration),指定哪些属性应该在控件上进行设置,声明部分是一系列的"属

随机推荐