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实现简单状态框架的方法
Mar 19 Python
使用优化器来提升Python程序的执行效率的教程
Apr 02 Python
Python面向对象编程基础解析(一)
Oct 26 Python
基于python实现在excel中读取与生成随机数写入excel中
Jan 04 Python
python机器学习理论与实战(六)支持向量机
Jan 19 Python
Python2.7 实现引入自己写的类方法
Apr 29 Python
一百多行python代码实现抢票助手
Sep 25 Python
Python进阶:生成器 懒人版本的迭代器详解
Jun 29 Python
python的debug实用工具 pdb详解
Jul 12 Python
Python使用selenium + headless chrome获取网页内容的方法示例
Oct 16 Python
解决django model修改添加字段报错的问题
Nov 18 Python
Python 添加文件注释和函数注释操作
Aug 09 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
请php正则走开
2008/03/15 PHP
如何使用jQuery+PHP+MySQL来实现一个在线测试项目
2015/04/26 PHP
Thinkphp实现自动验证和自动完成
2015/12/19 PHP
php生成复杂验证码(倾斜,正弦干扰线,黏贴,旋转)
2018/03/12 PHP
如何用js控制frame的隐藏或显示的解决办法
2013/03/20 Javascript
nodejs 提示‘xxx’ 不是内部或外部命令解决方法
2014/11/20 NodeJs
node.js中的fs.fsync方法使用说明
2014/12/15 Javascript
JavaScript使用指针操作实现约瑟夫问题实例
2015/04/07 Javascript
JavaScript实现Flash炫光波动特效
2015/05/14 Javascript
JS实现仿腾讯微博无刷新删除微博效果代码
2015/10/16 Javascript
javascript正则表达式定义(语法)总结
2016/01/08 Javascript
JavaScript 节流函数 Throttle 详解
2016/07/04 Javascript
从0开始学Vue
2016/10/27 Javascript
Javascript blur与click冲突解决办法
2017/01/09 Javascript
angular2+node.js express打包部署的实战
2017/07/27 Javascript
基于VUE.JS的移动端框架Mint UI的使用
2017/10/11 Javascript
JS回调函数 callback的理解与使用案例分析
2019/09/09 Javascript
微信小程序实现拼图小游戏
2020/10/22 Javascript
[02:31]2014DOTA2国际邀请赛2009专访:干爹表现出乎意料 看好DK杀回决赛
2014/07/20 DOTA
Python中的字典与成员运算符初步探究
2015/10/13 Python
python shell根据ip获取主机名代码示例
2017/11/25 Python
python3连接MySQL数据库实例详解
2018/05/24 Python
浅谈Python小波分析库Pywavelets的一点使用心得
2019/07/09 Python
Flask配置Cors跨域的实现
2019/07/12 Python
python 操作hive pyhs2方式
2019/12/21 Python
Python *args和**kwargs用法实例解析
2020/03/02 Python
解决pyecharts运行后产生的html文件用浏览器打开空白
2020/03/11 Python
Python爬虫基于lxml解决数据编码乱码问题
2020/07/31 Python
pycharm配置QtDesigner的超详细方法
2021/01/25 Python
匡威意大利官方商店 :Converse意大利
2018/11/27 全球购物
俄罗斯连接商品和买家的在线平台:goods.ru
2020/11/30 全球购物
财产公证书
2014/04/10 职场文书
捐资助学感谢信
2015/01/21 职场文书
放飞理想主题班会
2015/08/14 职场文书
2016年九九重阳节活动总结
2016/04/01 职场文书
一次SQL如何查重及去重的实战记录
2022/03/13 MySQL