PYQT5开启多个线程和窗口,多线程与多窗口的交互实例


Posted in Python onDecember 13, 2019

每点击一次按钮,弹出一个对话框(子窗口),同时开启一个子线程来执行任务并更新对话框内容,关闭对话框则关闭对应子线程

1. 建立一个简单的主界面和一个自定义对话框

PYQT5开启多个线程和窗口,多线程与多窗口的交互实例

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
 def setupUi(self, MainWindow):
  MainWindow.setObjectName("MainWindow")
  MainWindow.resize(327, 303)
  self.centralwidget = QtWidgets.QWidget(MainWindow)
  self.centralwidget.setObjectName("centralwidget")
  self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
  self.gridLayout.setObjectName("gridLayout")
  spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
  self.gridLayout.addItem(spacerItem, 0, 0, 1, 1)
  self.pushButton = QtWidgets.QPushButton(self.centralwidget)
  self.pushButton.setObjectName("pushButton")
  self.gridLayout.addWidget(self.pushButton, 0, 1, 1, 1)
  spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
  self.gridLayout.addItem(spacerItem1, 0, 2, 1, 1)
  MainWindow.setCentralWidget(self.centralwidget)
  self.menubar = QtWidgets.QMenuBar(MainWindow)
  self.menubar.setGeometry(QtCore.QRect(0, 0, 327, 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)
  self.pushButton.clicked.connect(MainWindow.open_dialog)
  QtCore.QMetaObject.connectSlotsByName(MainWindow)

 def retranslateUi(self, MainWindow):
  _translate = QtCore.QCoreApplication.translate
  MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
  self.pushButton.setText(_translate("MainWindow", "多线程弹窗"))


class Ui_Dialog(object):
 def setupUi(self, Dialog):
  Dialog.setObjectName("Dialog")
  Dialog.resize(369, 128)
  self.gridLayout = QtWidgets.QGridLayout(Dialog)
  self.gridLayout.setObjectName("gridLayout")
  self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
  self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
  self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
  self.buttonBox.setObjectName("buttonBox")
  self.gridLayout.addWidget(self.buttonBox, 1, 0, 1, 1)
  self.progressBar = QtWidgets.QProgressBar(Dialog)
  self.progressBar.setProperty("value", 24)
  self.progressBar.setObjectName("progressBar")
  self.gridLayout.addWidget(self.progressBar, 0, 0, 1, 1)

  self.retranslateUi(Dialog)
  self.buttonBox.accepted.connect(Dialog.accept)
  self.buttonBox.rejected.connect(Dialog.reject)
  QtCore.QMetaObject.connectSlotsByName(Dialog)

 def retranslateUi(self, Dialog):
  _translate = QtCore.QCoreApplication.translate
  Dialog.setWindowTitle(_translate("Dialog", "Dialog"))

2. 每点击一次按钮,打开一个弹窗

class DialogWindow(QDialog, Ui_Dialog):
 def __init__(self, parent=None):
  super(DialogWindow, self).__init__(parent)
  self.setupUi(self)


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
 def __init__(self, parent=None):
  super(MainWindow, self).__init__(parent)
  self.setupUi(self)

 def open_dialog(self):
  dialog = DialogWindow(self)
  dialog.show()


if __name__ == "__main__":
 app = QtWidgets.QApplication(sys.argv)
 mainWindow = MainWindow()
 mainWindow.show()
 sys.exit(app.exec_())

3. 打开弹窗的同时,打开一个子线程,更新对话框中的进度条

PYQT5开启多个线程和窗口,多线程与多窗口的交互实例

在子线程定义信号,关联对话框更新进度条的槽函数

class DialogWindow(QDialog, Ui_Dialog):
 def __init__(self, parent=None):
  super(DialogWindow, self).__init__(parent)
  self.setupUi(self)

 def update_progressbar(self, p_int):
  self.progressBar.setValue(p_int) # 更新进度条


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
 def __init__(self, parent=None):
  super(MainWindow, self).__init__(parent)
  self.setupUi(self)
  self.count = 0

 def open_dialog(self):
  dialog = DialogWindow(self)
  dialog.show()
  self.thread = RunThread(self.count)
  self.count += 1
  self.thread.update_pb.connect(dialog.update_progressbar) # 关联
  self.thread.start()


class RunThread(QThread):
 update_pb = pyqtSignal(int) # 定义更新进度条的信号

 def __init__(self, count):
  super().__init__()
  self.count = count

 def run(self):
  for i in range(100):
   print('thread%s' % self.count, i, QThread().currentThreadId())
   self.update_pb.emit(i)
   time.sleep(1)
  pass


if __name__ == "__main__":
 app = QtWidgets.QApplication(sys.argv)
 mainWindow = MainWindow()
 mainWindow.show()
 sys.exit(app.exec_())

4. 关闭对话框,则关闭对应子线程

在对话框中添加自定义信号,并重写关闭事件,在关闭窗口时发送关闭子线程的信号

class DialogWindow(QDialog, Ui_Dialog):
 stop_thread = pyqtSignal() # 定义关闭子线程的信号

 def __init__(self, parent=None):
  super(DialogWindow, self).__init__(parent)
  self.setupUi(self)

 def update_progressbar(self, p_int):
  self.progressBar.setValue(p_int)

 def closeEvent(self, event):
  self.stop_thread.emit()
  pass


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
 def __init__(self, parent=None):
  super(MainWindow, self).__init__(parent)
  self.setupUi(self)
  self.count = 0

 def open_dialog(self):
  dialog = DialogWindow(self)
  dialog.show()
  self.thread = RunThread(self.count)
  self.count += 1
  self.thread.update_pb.connect(dialog.update_progressbar)
  dialog.stop_thread.connect(self.thread.terminate)
  self.thread.start()


class RunThread(QThread):
 update_pb = pyqtSignal(int)

 def __init__(self, count):
  super().__init__()
  self.count = count

 def run(self):
  for i in range(1, 101):
   print('thread_%s' % self.count, i, QThread().currentThreadId())
   self.update_pb.emit(i)
   time.sleep(1)
  pass


if __name__ == "__main__":
 app = QtWidgets.QApplication(sys.argv)
 mainWindow = MainWindow()
 mainWindow.show()
 sys.exit(app.exec_())

5. 使用线程池QThreadPool管理子线程

使用QThreadPool, 线程需要继承QRunnable,而QRunnable只是namespace,没有继承QT的信号机制,

所以需要另外继承QObject来使用信号,我这里直接在线程中使用封装的信号向外部传递信息

class DialogWindow(QDialog, Ui_Dialog):
 stop_thread = pyqtSignal() # 定义关闭子线程的信号

 def __init__(self, parent=None):
  super(DialogWindow, self).__init__(parent)
  self.setupUi(self)

 def update_progressbar(self, p_int):
  self.progressBar.setValue(p_int)

 def closeEvent(self, event):
  self.stop_thread.emit()
  pass


class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
 def __init__(self, parent=None):
  super(MainWindow, self).__init__(parent)
  self.setupUi(self)
  self.count = 0
  self.pool = QThreadPool()
  self.pool.globalInstance()
  self.pool.setMaxThreadCount(10) # 设置最大线程数

 def open_dialog(self):
  dialog = DialogWindow(self)
  dialog.show()
  thread = RunThread(self.count)
  self.count += 1
  thread.signal.update_pb.connect(dialog.update_progressbar)
  # dialog.stop_thread.connect(thread.stop)
  # self.thread.start()
  self.pool.start(thread) # 线程池分配一个线程运行该任务


class Signal(QObject):
 update_pb = pyqtSignal(int)


class RunThread(QRunnable):
 def __init__(self, count):
  super().__init__()
  self.count = count
  self.signal = Signal() # 信号

 def run(self):
  for i in range(1, 101):
   print('thread_%s' % self.count, i, QThread().currentThreadId())
   self.signal.update_pb.emit(i)
   time.sleep(1)


if __name__ == "__main__":
 app = QtWidgets.QApplication(sys.argv)
 mainWindow = MainWindow()
 mainWindow.show()
 sys.exit(app.exec_())

QThreadPool没有释放正在运行的线程的方法

以上这篇PYQT5开启多个线程和窗口,多线程与多窗口的交互实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python  连接字符串(join %)
Sep 06 Python
python实现读取命令行参数的方法
May 22 Python
Python自动扫雷实现方法
Jul 25 Python
深入讲解Java编程中类的生命周期
Feb 05 Python
Python学习之Anaconda的使用与配置方法
Jan 04 Python
python使用锁访问共享变量实例解析
Feb 08 Python
Python3使用正则表达式爬取内涵段子示例
Apr 22 Python
python验证码图片处理(二值化)
Nov 01 Python
python飞机大战pygame游戏背景设计详解
Dec 17 Python
python3 循环读取excel文件并写入json操作
Jul 14 Python
详解Pycharm安装及Django安装配置指南
Sep 15 Python
Python控制台输出俄罗斯方块移动和旋转功能
Apr 18 Python
浅谈PyQt5中异步刷新UI和Python多线程总结
Dec 13 #Python
python编写微信公众号首图思路详解
Dec 13 #Python
selenium+python实现自动登陆QQ邮箱并发送邮件功能
Dec 13 #Python
python中设置超时跳过,超时退出的方式
Dec 13 #Python
python opencv实现gif图片分解的示例代码
Dec 13 #Python
python多进程并发demo实例解析
Dec 13 #Python
使用Matplotlib 绘制精美的数学图形例子
Dec 13 #Python
You might like
声音就能俘获人心,蕾姆,是哪个漂亮小姐姐配音呢?
2020/03/03 日漫
php session_start()关于Cannot send session cache limiter - headers already sent错误解决方法
2009/11/27 PHP
解析php通过cookies获取远程网页的指定代码
2013/06/25 PHP
thinkPHP3.2.2框架行为扩展及demo示例
2018/06/19 PHP
防止页面被iframe(兼容IE,Firefox火狐)
2010/07/04 Javascript
JavaScript闭包函数访问外部变量的方法
2014/08/27 Javascript
JS实现OCX控件的事件响应示例
2014/09/17 Javascript
JavaScript代码性能优化总结(推荐)
2016/05/16 Javascript
ajax图片上传,图片异步上传,更新实例
2016/12/30 Javascript
初识NodeJS服务端开发入门(Express+MySQL)
2017/04/07 NodeJs
angularJs中datatable实现代码
2017/06/03 Javascript
详解Vue CLI3 多页应用实践和源码设计
2018/08/30 Javascript
layer.open组件获取弹出层页面变量、函数的实例
2019/09/25 Javascript
element-ui table组件如何使用render属性的实现
2019/11/04 Javascript
[03:36]DOTA2完美大师赛coL战队趣味视频——我演你猜
2017/11/23 DOTA
[42:20]Secret vs Liquid 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/17 DOTA
Python查找函数f(x)=0根的解决方法
2015/05/07 Python
python3获取当前文件的上一级目录实例
2018/04/26 Python
python中plot实现即时数据动态显示方法
2018/06/22 Python
详解Python可视化神器Yellowbrick使用
2019/11/11 Python
Python 日期的转换及计算的具体使用详解
2020/01/16 Python
python定义类self用法实例解析
2020/01/22 Python
tensorflow之变量初始化(tf.Variable)使用详解
2020/02/06 Python
在PyTorch中使用标签平滑正则化的问题
2020/04/03 Python
各大浏览器 CSS3 和 HTML5 兼容速查表 图文
2010/04/01 HTML / CSS
网络工程师的自我评价
2013/10/02 职场文书
市场营销求职信范文
2014/02/21 职场文书
人事专员工作职责
2014/02/22 职场文书
大学自主招生推荐信
2014/05/10 职场文书
合同意向书范本
2014/07/30 职场文书
群众路线教育实践活动调研报告
2014/11/03 职场文书
2016高考冲刺决心书
2015/09/23 职场文书
python 统计代码耗时的几种方法分享
2021/04/02 Python
Python-typing: 类型标注与支持 Any类型详解
2021/05/10 Python
快速学习Oracle触发器和游标
2021/06/30 Oracle
Mysql中常用的join连接方式
2022/05/11 MySQL