pyqt5处理多线程主要有三种方法:

  1. 使用计时器模块QTimer
  2. 使用多线程模块QThread
  3. 使用事件处理功能

QTimer相当于一个定时器,每当定时器时间溢出后,会执行相关的函数。这个时候程序会从主线程界面跳到QTimer函数中,如果QTimer函数中有延时或者处理时间较长,就会出现界面失去响应,造成界面卡顿的现象。

QThread等于新开一个线程专门处理耗时间的程序,UI主线程显示界面,当子线程处理好数据后通过自定义的信号与槽,将数据交给主线程刷新界面。由于UI主线程一直运行,子线程的延时,耗时程序与主线程无关,所以不会有卡顿的现象。

事件处理功能:相当于在耗时的程序中,主动刷新界面,使人觉得流畅。

使用QThread能够很好得完成UI与数据处理之间的关系。

通过QThread实现多线程

1.新建类Timer_thread(),继承QThread
2.自定义槽信号sinout(可以定义槽函数中接收参数类型,数字,文本,list等等)
3.重写run()函数,将线程需要执行的函数放在里面
4.在UI类中将Timer_thread实例化
5.通过.start()方法使线程执行,当线程数据处理完成后,通过信号与槽将数据发到槽函数中,槽函数处理数据并显示到界面中.

通过QTimer实现多线程

  1. 首先要实例化一个定时器QTimer
  2. 将定时器的timeout信号连接到对应的槽函数
  3. 最后通过.start()方法进行启动。

通过事件处理功能

这种方法不常用,主要原理是:在卡顿的地方使用:QtWidgets.QApplication.processEvents()去刷
新一下界面

'''
Description: 
Version: 2.0
Autor: zxm
Date: 2021-11-16 00:57:57
LastEditors: zxm
LastEditTime: 2021-11-17 01:22:01
'''
"""
导入界面相关的模块和包
"""
from PyQt5 import QtCore, QtGui, QtWidgets
from test import Ui_MainWindow
import sys
from PyQt5.QtCore import QThread, QObject, QTimer, pyqtSignal, pyqtSlot
import datetime
import time

"""
新建一个类,并且继承QtWidgets.QMainWindow,以及
Ui文件中自动生成的类Ui_MainWindow
"""

class Test_win(QtWidgets.QMainWindow,Ui_MainWindow):
    def __init__(self):
        super(Test_win,self).__init__()                 # 父类初始化
        self.setupUi(self)                              # 界面控件生成及布局
        self.timethread = Time_thread()
        self.timethread.sinout.connect(self.Refresh_label)
        self.test_pushButton.clicked.connect(self.thread_start)
        self.test_pushButton.clicked.connect(self.count_start)

        self.countTimer = QTimer(self)                      # 实例化一个计时器
        self.countTimer.timeout.connect(self.timeout_fun)   # 将timeout与槽函数相连,计时器溢出时执行槽函数刷新界面
        self.times = 0

    def timeout_fun(self):
        self.times += 1
        # time.sleep(1)											# 本质上QTimer的槽函数还是运行在界面UI主线程中,如果出现延时函数会出现卡顿现象,尽量不要在主线程中使用延时函数
        self.count_label.setText(str(self.times))           # 刷新界面

    def count_start(self):
        self.countTimer.start(1000)                         # 开始计时,定时1s执行一次

    
    def thread_start(self):
        self.timethread.start()

    


    def func(self):                                     # 类的方法
        print('hellow pyqt5!')

    def Refresh_label(self,now_time):
        self.test_label.setText(now_time)



class Time_thread(QThread):
    sinout = pyqtSignal(str)

    def __init__(self):
        super(Time_thread,self).__init__()
        print('Time_thread Start...')
    
    def run(self):
        while(True):
            now = datetime.datetime.now()
            str_time = str(now.hour) + ":" + str(now.minute) + ":" + str(now.second)
            self.sinout.emit(str_time)
            time.sleep(1)
        
        

    def __del__(self):
        print('Time_thread Over...')



if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    win = Test_win()                                    # 实例化一个类
    win.show()                                          # 类的方法,将界面显示出来
    win.func()                                          # 自定义类方法的调用
    sys.exit(app.exec_())

在这里插入图片描述
最终实现点击按键后:
左边显示实时时间,1s中刷新一次,这个延时是在子线程中完成的,因此不会造成卡顿;
右边通过QTimer,1s钟刷新一次,延时是通过计时器来做的,但是在timeout连接到的槽函数不要使用延时函数,或者说在UI主线程中的代码不要有延时函数,否者会造成界面无响应卡顿。

界面代码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'test.ui'
#
# Created by: PyQt5 UI code generator 5.11.3
#
# WARNING! All changes made in this file will be lost!

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.test_label = QtWidgets.QLabel(self.centralwidget)
        self.test_label.setGeometry(QtCore.QRect(300, 210, 54, 12))
        self.test_label.setObjectName("test_label")
        self.test_pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.test_pushButton.setGeometry(QtCore.QRect(350, 270, 75, 23))
        self.test_pushButton.setObjectName("test_pushButton")
        self.count_label = QtWidgets.QLabel(self.centralwidget)
        self.count_label.setGeometry(QtCore.QRect(460, 210, 54, 12))
        self.count_label.setObjectName("count_label")
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.test_label.setText(_translate("MainWindow", "TIME"))
        self.test_pushButton.setText(_translate("MainWindow", "TEST"))
        self.count_label.setText(_translate("MainWindow", "计数"))



Ui文件

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QLabel" name="test_label">
    <property name="geometry">
     <rect>
      <x>300</x>
      <y>210</y>
      <width>54</width>
      <height>12</height>
     </rect>
    </property>
    <property name="text">
     <string>TIME</string>
    </property>
   </widget>
   <widget class="QPushButton" name="test_pushButton">
    <property name="geometry">
     <rect>
      <x>350</x>
      <y>270</y>
      <width>75</width>
      <height>23</height>
     </rect>
    </property>
    <property name="text">
     <string>TEST</string>
    </property>
   </widget>
   <widget class="QLabel" name="count_label">
    <property name="geometry">
     <rect>
      <x>460</x>
      <y>210</y>
      <width>54</width>
      <height>12</height>
     </rect>
    </property>
    <property name="text">
     <string>计数</string>
    </property>
   </widget>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>23</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐