目录
① 如果Qt只采用单线程任务的方式,当遇到数据处理慢的情形时,会出现GUI卡死的情况。
② 使用下述例子展示单线程任务的缺陷:

③ 代码:
- 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可以正常工作,输入框可以正常显示输入的内容。


① 通过继承父类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 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_()
③ 结果展示:


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