PyQt5学习笔记--多线程处理、数据交互

目录

1--引入多线程的原因

2--PyQt多线程的基本知识

3--多线程登录程序的实例

4--参考


1--引入多线程的原因

① 如果Qt只采用单线程任务的方式,当遇到数据处理慢的情形时,会出现GUI卡死的情况。

② 使用下述例子展示单线程任务的缺陷:

PyQt5学习笔记--多线程处理、数据交互_第1张图片

③ 代码:

import sys
import time

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


class MyThread(QThread):
    def __init__(self):
        super().__init__()

    def run(self):
        for i in range(10):
            print("是MyThread线程中执行....%d" % (i + 1))
            time.sleep(1)

class MyWin(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()
    def init_ui(self):
        self.ui = uic.loadUi("./thread.ui")

        # 从ui文件中加载控件
        line_edit = self.ui.lineEdit
        btn1 = self.ui.pushButton
        btn2 = self.ui.pushButton_2

        # 控件绑定槽函数
        btn1.clicked.connect(self.click_1)
        btn2.clicked.connect(self.click_2)
        
    def click_1(self):
        for i in range(10):
            print("是UI线程中执行....%d" % (i + 1))
            time.sleep(1)

    def click_2(self):
        self.my_thread = MyThread() # 创建线程
        self.my_thread.start() # 开始线程


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

④ 结果展示:

当点击第一个button时,GUI会出现卡顿无法显示输出的问题;当点击第二个button时,GUI可以正常工作,输入框可以正常显示输入的内容。

PyQt5学习笔记--多线程处理、数据交互_第2张图片

PyQt5学习笔记--多线程处理、数据交互_第3张图片

2--PyQt多线程的基本知识

① 通过继承父类QThread可以新建子线程;

② 线程之间可以通过信号进行交互,并通过其槽函数执行对应的功能;

③ 常用函数:(后面会专门写一篇笔记,其内容是如何在线程之间通过信号传递opencv图片、numpy数组等数据格式)

signal = pyqtSignal(str); # 创建信号

signal.emit(json); # 发送信号

json = json.dumps(data); # 将数据序列化封装

data = json.loads(json); # 将数据还原

3--多线程登录程序的实例

① 基于Qt Designer设计 ui 文件:

PyQt5学习笔记--多线程处理、数据交互_第4张图片

 ② 代码:

import json
import sys
import time

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5 import uic

# 子线程
class LoginThread(QThread):
    # 创建信号 接受字符串(这里用于主线程向子线程传递信息)
    start_login_signal = pyqtSignal(str) 

    def __init__(self, signal):
        super().__init__()
        # 信号绑定槽函数
        self.start_login_signal.connect(self.login_by_requests)

        self.login_complete_signal = signal

    def login_by_requests(self, user_password_json):
        # 将json字符串转换
        user_password_dict = json.loads(user_password_json)
        user_name = user_password_dict.get("user_name")
        password = user_password_dict.get("password")
        print(user_name, password)
        
        # 比对登录信息,返回登录状态(可自由扩充)
        if user_name == "liujinfu" and password == "liujinfu":
            self.login_complete_signal.emit(json.dumps(True)) # 返回True
        else:
            self.login_complete_signal.emit(json.dumps(False)) # 返回False

    def run(self):
        while True: # 让子线程一直运行,等待主线程(ui线程)下发的任务
            print("子线程正在等待执行....")
            time.sleep(2)

# 主线程
class MyWindow(QWidget):
    # 创建信号(这里用于子线程向主线程返回信息)
    login_status_signal = pyqtSignal(str)  

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

    def init_ui(self):
        self.ui = uic.loadUi("./login.ui")  # 加载由Qt Designer设计的ui文件

        self.user_name_qwidget = self.ui.lineEdit  # 用户名输入框
        self.password_qwidget = self.ui.lineEdit_2  # 密码输入框
        self.login_btn = self.ui.pushButton  # 登录按钮
        self.forget_btn = self.ui.pushButton_2  # 忘记密码按钮
        self.text_browser = self.ui.textBrowser  # 文本显示区域

        # 绑定槽函数
        self.login_btn.clicked.connect(self.login)

        self.login_thread = LoginThread(self.login_status_signal)  # 登录子线程
        self.login_thread.start() # 让子线程开始工作

        self.login_status_signal.connect(self.login_status)

    def login(self):
        # 实现登录函数
        self.user_name = self.user_name_qwidget.text()
        self.password = self.password_qwidget.text()
        # 发送信号,让子线程开始登录
        self.login_thread.start_login_signal.emit(json.dumps({"user_name": self.user_name, "password": self.password}))

    def login_status(self, status):
        # 根据登录状态打印信息(可自由扩充)
        if json.loads(status):
            self.text_browser.setText("Welcome %s !" % self.user_name)
            self.text_browser.repaint()
        else:
            self.text_browser.setText("User_name or password is not correct, please try again !")
            self.text_browser.repaint()

if __name__ == '__main__':
    app = QApplication(sys.argv)  # 创建对象

    w = MyWindow()
    # 展示窗口
    w.ui.show()

    # 程序进行循环等待状态
    app.exec_()

③ 结果展示:

PyQt5学习笔记--多线程处理、数据交互_第5张图片

PyQt5学习笔记--多线程处理、数据交互_第6张图片

注:后面会专门写一篇笔记,其内容是如何在线程之间通过信号传递opencv图片、numpy数组等数据格式

4--参考

PyQt5 快速入门

你可能感兴趣的:(学习)