目录
1--引入多线程的原因
2--PyQt多线程的基本知识
3--多线程登录程序的实例
4--参考
① 如果Qt只采用单线程任务的方式,当遇到数据处理慢的情形时,会出现GUI卡死的情况。
② 使用下述例子展示单线程任务的缺陷:
③ 代码:
import sys
import timefrom PyQt5 import uic
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import QWidget, QApplicationclass 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.lineEditbtn1 = self.ui.pushButtonbtn2 = 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可以正常工作,输入框可以正常显示输入的内容。
① 通过继承父类QThread可以新建子线程;
② 线程之间可以通过信号进行交互,并通过其槽函数执行对应的功能;
③ 常用函数:(后面会专门写一篇笔记,其内容是如何在线程之间通过信号传递opencv图片、numpy数组等数据格式)
signal = pyqtSignal(str); # 创建信号signal.emit(json); # 发送信号json = json.dumps(data); # 将数据序列化封装data = json.loads(json); # 将数据还原
① 基于Qt Designer设计 ui 文件:
② 代码:
import json
import sys
import timefrom 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 = signaldef 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)) # 返回Trueelse:self.login_complete_signal.emit(json.dumps(False)) # 返回Falsedef 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_()
③ 结果展示:
注:后面会专门写一篇笔记,其内容是如何在线程之间通过信号传递opencv图片、numpy数组等数据格式
PyQt5 快速入门