pyqt5多线程(子线程执行将结果返回到主线程上,提示对话框)

pyqt5多线程(子线程执行将结果返回到主线程上,提示对话框)

1.为什么要多线程执行

在主线程ui界面点击登录后,加延时10s,(模拟调用接口登录,假设耗时10s),ui主线程在等待请求返回结果,ui界面卡主,转圈,如下图。这个现象在软件中肯定是不能出现的!
pyqt5多线程(子线程执行将结果返回到主线程上,提示对话框)_第1张图片

2.解决思路

为了解决这个问题,就必须引入多线程,在点击按钮后,主线程触发一个子线程去执行,让子线程执行耗时任务,主线程就会处于空闲状态,那么界面就不会出现转圈卡顿的现象!当子线程任务执行完成后,给主线程自定义信号发送消息,主线程收到,消息,反馈到主界面来!

pyqt5多线程(子线程执行将结果返回到主线程上,提示对话框)_第2张图片

3.完整的案例代码

完整的案例代码,如下,点击登录按钮是走主线程执行,会出现卡顿;点击忘记密码按钮,会触发子线程执行任务,主线程就处于空闲状态。当子线程任务执行完成后,给主线程自定义信号发送消息,主线程收到,消息,反馈到主界面来!

https://gitee.com/HP_mojin/pyqt_ui/tree/master/pyqt_ui_01

main.py 文件

import sys
import time

from PyQt5 import uic,QtWidgets
from PyQt5.Qt import QApplication, QWidget, QThread
from PyQt5.QtCore import pyqtSignal


class MyThread(QThread): #子线程
    def __init__(self,signal,kwargs ):
        super().__init__()

        self.start_complete_signal=signal #将自定义信号传递过来,
        self.kwargs=kwargs

    def run(self):

        #延时 10秒
        for i in range(10):
            print("是MyThread线程中执行....%d" % (i + 1))
            time.sleep(1)

        self.start_complete_signal.emit(f'子线程,运行完成:{self.kwargs}') #给自定义信号发送消息



class MyWin(QWidget):#主线程 主界面

    # 声明一个信号,只能写在函数外面
    forgot_status_signal = pyqtSignal(str) #自定义信号,接受子线程,执行完成的消息

    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):#主界面元素


        self.ui = uic.loadUi("./qt_ui/login_ui.ui") # 加载 qt 设计师,设计出的ui

        # 从ui文件中加载控件
        login_btn1 = self.ui.pushButton #登录按钮
        forgot_btn2 = self.ui.pushButton_2  #忘记密码按钮

        # 给2个按钮绑定槽函数
        login_btn1.clicked.connect(self.login)  # 绑定登录按钮的槽函数
        forgot_btn2.clicked.connect(self.forgot_password)  # 绑定忘记密码按钮的槽函数

        self.forgot_status_signal.connect(self.forgot_status) #绑定自定义信号的槽函数,收到子线程消息,执行绑定的槽函数


    def login(self): #登录按钮绑定的槽函数,主线程执行,出现卡顿

        #耗时 延时10秒
        for i in range(10):
            print("是UI线程中执行....%d" % (i + 1))
            time.sleep(1)

        user_name=self.ui.lineEdit.text() #获取账号输入框text信息
        password = self.ui.lineEdit_2.text()  #获取密码输入框text信息

        dic={
            "user_name":user_name,
            "password":password
        }

        #将返回消息写入显示框
        self.ui.textEdit.setText(f'主线程运行完成:{dic}')
        #输入框刷新显示
        self.ui.textEdit.repaint()

        # 对话框弹框
        QtWidgets.QMessageBox.information(None, '主线程', f'主线程运行完成:{dic}', QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                                          QtWidgets.QMessageBox.Yes)


    def forgot_password(self): #忘记密码按钮 绑定的槽函数,执行后启动子线程
        user_name=self.ui.lineEdit.text() #获取账号输入框text信息
        password = self.ui.lineEdit_2.text()  #获取密码输入框text信息

        dic={
            "user_name":user_name,
            "password":password
        }


        self.my_thread = MyThread(self.forgot_status_signal,dic)  # 创建线程
        self.my_thread.start()  # 开始线程 启动子线程执行任务





    def forgot_status(self,srt): #收到子线程消息,执行绑定的槽函数
        print(f'收到子线程消息:{srt}')
        print("主线程:收到了槽函数,打印消息")

        #将返回消息写入显示框
        self.ui.textEdit.setText(srt)
        #输入框刷新显示
        self.ui.textEdit.repaint()

        # 对话框弹框
        QtWidgets.QMessageBox.information(None, '主线程打印', srt, QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No,
                                          QtWidgets.QMessageBox.Yes)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    myshow = MyWin()
    myshow.ui.show()
    app.exec()

self.ui = uic.loadUi(“./qt_ui/login_ui.ui”) # 加载 qt 设计师,设计出的ui

login_ui.ui文件


<ui version="4.0">
 <class>MainWindowclass>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0x>
    <y>0y>
    <width>819width>
    <height>600height>
   rect>
  property>
  <property name="windowTitle">
   <string>MainWindowstring>
  property>
  <widget class="QWidget" name="centralwidget">
   <widget class="QWidget" name="">
    <property name="geometry">
     <rect>
      <x>30x>
      <y>120y>
      <width>751width>
      <height>271height>
     rect>
    property>
    <layout class="QHBoxLayout" name="horizontalLayout_4">
     <item>
      <layout class="QVBoxLayout" name="verticalLayout">
       <item>
        <layout class="QHBoxLayout" name="horizontalLayout">
         <item>
          <widget class="QLabel" name="label">
           <property name="text">
            <string>账号:string>
           property>
          widget>
         item>
         <item>
          <widget class="QLineEdit" name="lineEdit"/>
         item>
        layout>
       item>
       <item>
        <layout class="QHBoxLayout" name="horizontalLayout_2">
         <item>
          <widget class="QLabel" name="label_2">
           <property name="text">
            <string>密码:string>
           property>
          widget>
         item>
         <item>
          <widget class="QLineEdit" name="lineEdit_2"/>
         item>
        layout>
       item>
       <item>
        <layout class="QHBoxLayout" name="horizontalLayout_3">
         <item>
          <widget class="QPushButton" name="pushButton">
           <property name="text">
            <string>登录string>
           property>
          widget>
         item>
         <item>
          <widget class="QPushButton" name="pushButton_2">
           <property name="text">
            <string>忘记密码?string>
           property>
          widget>
         item>
        layout>
       item>
      layout>
     item>
     <item>
      <widget class="QTextEdit" name="textEdit"/>
     item>
    layout>
   widget>
  widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0x>
     <y>0y>
     <width>819width>
     <height>23height>
    rect>
   property>
  widget>
  <widget class="QStatusBar" name="statusbar"/>
 widget>
 <resources/>
 <connections/>
ui>


login_ui.py 文件

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

# Form implementation generated from reading ui file 'login_ui.ui'
#
# Created by: PyQt5 UI code generator 5.15.9
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again.  Do not edit this file unless you know what you are doing.


from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(819, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(30, 120, 751, 271))
        self.widget.setObjectName("widget")
        self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.widget)
        self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_4.setObjectName("horizontalLayout_4")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label = QtWidgets.QLabel(self.widget)
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)
        self.lineEdit = QtWidgets.QLineEdit(self.widget)
        self.lineEdit.setObjectName("lineEdit")
        self.horizontalLayout.addWidget(self.lineEdit)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.label_2 = QtWidgets.QLabel(self.widget)
        self.label_2.setObjectName("label_2")
        self.horizontalLayout_2.addWidget(self.label_2)
        self.lineEdit_2 = QtWidgets.QLineEdit(self.widget)
        self.lineEdit_2.setObjectName("lineEdit_2")
        self.horizontalLayout_2.addWidget(self.lineEdit_2)
        self.verticalLayout.addLayout(self.horizontalLayout_2)
        self.horizontalLayout_3 = QtWidgets.QHBoxLayout()
        self.horizontalLayout_3.setObjectName("horizontalLayout_3")
        self.pushButton = QtWidgets.QPushButton(self.widget)
        self.pushButton.setObjectName("pushButton")
        self.horizontalLayout_3.addWidget(self.pushButton)
        self.pushButton_2 = QtWidgets.QPushButton(self.widget)
        self.pushButton_2.setObjectName("pushButton_2")
        self.horizontalLayout_3.addWidget(self.pushButton_2)
        self.verticalLayout.addLayout(self.horizontalLayout_3)
        self.horizontalLayout_4.addLayout(self.verticalLayout)
        self.textEdit = QtWidgets.QTextEdit(self.widget)
        self.textEdit.setObjectName("textEdit")
        self.horizontalLayout_4.addWidget(self.textEdit)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 819, 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.label.setText(_translate("MainWindow", "账号:"))
        self.label_2.setText(_translate("MainWindow", "密码:"))
        self.pushButton.setText(_translate("MainWindow", "登录"))
        self.pushButton_2.setText(_translate("MainWindow", "忘记密码?"))

你可能感兴趣的:(pyqt5,qt,开发语言)