(详细分析)python PyQt5图形界面编程(含pyqtgraph画3D散点图、父子窗口间传递信息、pyinstaller打包可执行exe文件)

本文主要是介绍(详细分析)python PyQt5图形界面编程(含pyqtgraph画3D散点图、父子窗口间传递信息、pyinstaller打包可执行exe文件),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

介绍

 layout

制作应用程序,pyinstaller

单选框

tab页中布局

显示样式

画3D散点图

子窗口与父窗口信息交互


  • 介绍

    • 网站http://www.python3.vip/tut/py/gui/qt_09/
    • Tkinter、wxPython、PySide2、PyQt5
    • 按住Ctrl拖动控件,直接复制
  •  layout

    • sizepolicy控件大小
    • 按住Ctrl键拖动就是复制
    • 调整layout中控件的大小比例,优先使用layout的layoutStrentch属性来控制
    • 把控件挤小,可使用horizontal spacer
  • 制作应用程序,pyinstaller

    • 打包完之后会有两个文件夹build和dist,build不用管,dist里的是你需要的exe文件及相关东西。
    • 注意运行的时候,若代码编写时使用的静态加载(load)方法加载的UI文件,使用pyinstaller打包完后,需要把ui文件拷贝到生成的可执行文件中,不然会报错。
    • 举例:命令行中运行pyinstall httpclient.py --noconsole --hidden-import PySide2.QtXml
      • 其中--noconsole指运行exe时不出现调试窗口(类似于你直接在pycharm中run后,显示错误的底部的4:run窗口)。如果要测试,可以去掉该命令,从而保留调试窗口,出现的错误会在该窗口中显示。--hidden-import PySide2.QtXml是因为这个QtXml库是动态导入,需要我们告诉PyInstaller,不然运行exe文件后,会在调试窗口中报错:No module named XXXX
    • # 添加主窗口图标(打开EXE之后左上角显示的图标
      # from PySide2.QtGui import QIcon
      #
      # app = QApplication([])
      # # 加载icon
      # app.setWindowIcon(QIcon('logo.png'))# 应用程序图标,打包成的exe文件的图标
      # 制作程序的时候,写上
      # pyinstaller httpclient.py --noconsole --hidden-import PySide2.QtXml --icon="logo.ico"
      # 注意参数一定是.ico文件,不能使png等图片文件,可以通过在线的png转ico文件网站,生成ico
      # 比如https://www.zamzar.com/convert/png-to-ico/或者https://www.easyicon.net/covert/
    • 使用pyinstaller过程中遇到的问题及解决办法:
      • https://blog.csdn.net/weixin_42052836/article/details/82315118(Pyinstaller 打包发布经验总结)
      • https://blog.csdn.net/qq_38232378/article/details/95767597?utm_medium=distribute.pc_relevant.none-task-blog-title-2&spm=1001.2101.3001.4242(解决PyInstaller vcruntime140.dll没有被指定在Windows上运行)
      • 命令(生成单个程序,附带图标,生成在指定文件夹,使用upx压缩)
      • pyinstaller -F C:\Users\levovozzb\Desktop\bag\sp.py --distpath=C:\Users\levovozzb\Desktop\bag -i C:\Users\levovozzb\Desktop\bag\cs.ico --upx-dir=D:\ThunderDownload\upx-3.96-win64\upx.exepyinstaller -F 待打包py文件路径  ----distpath=程序指定生成的文件夹路径  -i  图标ico地址  --upx-dir=程序upx.exe的存放路径upx的下载网址:https://github.com/upx/upx/releases/tag/v3.95

         

      • 若使用upx进行打包,upx is not avaliable报错
        • 解压安装包得upx.exe文件,将exe拷贝到pyinstaller目录下,我的是E:\anaconda\Scripts
        • 虚拟纯python环境中,放的是C:\Users\qq154\.virtualenvs\htkjproject-9aXzGckk\Scripts
      • 查看第三方包版本号pip list或者pip show XXX
      • 安装特定版本的第三方包pip install XXX==5.15.0
      • 苦苦处理两周的问题终于解决了。通过把相关包位置加到系统环境变量中或者直接都打包进去是最有效果的。简单粗暴,之后再慢慢的缩减不需要的包即可。我的问题是通过在.spec文件中处理,再打包解决的。流程如下:
      • a = Analysis(['Client.py'],pathex=['E:\\PyCharm 2019.1.2\\pycharmprojects\\htkjproject', 'E:\\anaconda\\Lib\\site-packages\\PyQt5\\Qt\\bin', 'E:\anaconda\Lib\site-packages', 'E:\anaconda\Lib\site-packages\PyQt5', 'E:\anaconda\Lib\site-packages\pyqtgraph'],binaries=[],datas=[],hiddenimports=['PyQt5.QtOpenGL'],hookspath=[],runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False)# 打包出来的有290M(落泪.jpg),慢慢删减之后再更

         

      • 另外,如果使用anaconda的集成python环境,一般打出来的包会很大。。。。解决方式https://www.zhihu.com/question/268397385?sort=created( 用pipenv创建纯python的虚拟环境),https://blog.csdn.net/frostime/article/details/90523062(此在虚拟环境中,也可以直接pip安装,用pipenv install安装第三方包要检查,太慢,因此推荐pip install)
      • 在解决包很大的过程中,尝试在虚拟纯python环境中打包遇到问题:
      • “could not find or load the Qt platform plugin ”windows", this application failed to start because no qt platform plugin could be initialized

      • 发现当把环境变量中的QT_QPA_PLATFORM_PLUGIN_PATH设置为虚拟环境中pyqt5的plugins路径就可以运行,具体原因尚未清楚。而且显然这样对软件的可移植性有很大限制。换台主机就要配置变量是一件很Emm的事情。。。https://www.thetopsites.net/article/50550987.shtml
        • oh,终于解决了。参考https://stackoverflow.com/questions/47468705/pyinstaller-could-not-find-or-load-the-qt-platform-plugin-windows中回答的办法,不用管环境变量了,copying the ~PyQt5\Qt\plugins\platforms folder from the program's directory, generated by using pyinstaller --onedir main.py, to the folder holding the .exe file.即可
      • 总而言之,我在项目中解决文件过大的过程为:
      • # 在命令行中输入# 先基于对应版本的python生成虚拟python环境
        pipenv install --python 3.7# 启动虚拟环境
        pipenv shell# 安装pyinstaller
        pip install pyinstaller# 安装UI所需的包
        pip install pyopengl
        pip install pyqtgraph
        ...# 安装完之后打包
        pyinstaller -F client.py
        # -F选项为生成一个文件,会保留调试窗,若不想保留可以使用-Fw# 运行生成的.exe,根据调试窗的问题完善代码。若有其他问题可以在.spec文件中修改之后,使用如下语句打包:
        pyinstaller -F client.spec

         

  • 单选框

    • 同一组的按钮,Ctrl多选右键button group建立新的按钮组
  • tab页中布局

    • tab widget中的tab布局,直接右键是没有layout选项的,要在他右上角的对象的框 的上层tabwidget右键才有layout
  • 显示样式

    • 参考http://www.python3.vip/tut/py/gui/qt_09/
    • QSS类似于CSS,
    • 根据object(ID)修改,语言加#,根据class选不加
    • 选中最上mainwindow,下面属性中有个stylesheet,点一下,选三个点,输入样式代码
    • selector,与webcss的语法基本没区别。
    •  字体font-family,大小font-size,颜色color
    •  qt修改style之后有个bug,得去掉style代码之后,重新输入正确的
    • flat勾选之后,按钮的边框就不见了
    • 可以自己加动态属性,在property下面的框选加号,一般选string,然后选择性的控制部分控件的style
    • 修改某控件内部,比如tabwidget的内容的字体颜色,#tabWidget * {\n    color:red\n}
      • 若只修改直接子节点的style,则#tabWidget > * {}
      • 空格是内部的所有
    • 调色,alpha通道是调透明度
    • Pseudo-States伪状态
      • QPushButton:hover {color: red} hover悬浮,鼠标放到此位置时变化
      • disable状态,:disabled
      • 鼠标悬浮并且处于勾选checked状态,:hover:checked
      • QPushButton:hover{font-family:微软雅黑;font-size:15px;color: #1d649c;}

         

    • 指定背景色,background-color,背景图片background-image

    • 边框

    • 间隔,对外的margin四个就上右下左,顺时针,从上开始,也可margin-top,元素内容到内边框的边界为padding

    • 优先级
      • 越靠近的style优先级越高,可直接针对对象修改style
      • 样式官方文档https://doc.qt.io/qt-5/stylesheet-reference.html#list-of-properties
    • 多线程后台任务
      • 遇到较耗时的任务时,最好创建新的子线程去执行,避免主线程阻塞
      • 把要实现的功能做成函数,然后t = Thread(target=run)    t.start()
    • 第三方画图控件plotwidget载入,https://www.bilibili.com/video/av78483752?p=3
      • 用widget占个位,右键promote,提升类,类名即PlotWidget,头文件为其所在的库,即from 头文件 import PlotWidget
      • 注意没有core,图中仅举例
    • 导入文件(即load)时,pyside2要比pyqt5多个注册,即在loader.load(“main.ui”)前loader.registerCustomWidget(pg.PlotWidget)。即要把PlotWidget从哪儿来的要注册一下
    •  轴刻度为字符串功能,获取鼠标所在处刻度值
      • http://www.python3.vip/tut/py/gui/pyqtgraph-2/
    • 内嵌web浏览器
      •  
    •  将ui文件转换为python代码,pycharm中选中ui文件,最上栏tools-external tools选择pyUIC,即完成
  • 画3D散点图

    • 详细的示例分析见:
      • https://blog.csdn.net/qq_38025771/article/details/109896143
    • 需要采用的
      • pyqtgraph.opengl
      • opengl中的GLViewWidget
    • pyqtgraph功能强大,使用pip安装好后,可以在命令行中运行下行代码,查看pyqtgra图例
      • python -m pyqtgraph.examples
    • 推荐资料
      • https://zmister.com/archives/187.html(做了解用)
      • https://blog.csdn.net/API1_7/article/details/98249965(画图需要使用定时器,多线程,建议单独线程画图)
    • 采用普通widget升级(promote)到GLViewWidget
    • #设置最小化与最大化按钮
      self.setWindowFlags(QtCore.Qt.Window)
    •  UI布局文件:
    • # NodeStatus.py
      from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_NodeStatus(object):def setupUi(self, NodeStatus):NodeStatus.setObjectName("NodeStatus")NodeStatus.resize(695, 401)sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum)sizePolicy.setHorizontalStretch(0)sizePolicy.setVerticalStretch(0)sizePolicy.setHeightForWidth(NodeStatus.sizePolicy().hasHeightForWidth())NodeStatus.setSizePolicy(sizePolicy)NodeStatus.setStyleSheet("*{    \n""    font-family:微软雅黑;\n""    font-size:15px;\n""    color: #1d649c;\n""}\n""")self.verticalLayout = QtWidgets.QVBoxLayout(NodeStatus)self.verticalLayout.setObjectName("verticalLayout")self.guiplot = GLViewWidget(NodeStatus)self.guiplot.setObjectName("guiplot")self.guiplot.opts['distance'] = 50  # 设置初始镜头高度self.verticalLayout.addWidget(self.guiplot)self.retranslateUi(NodeStatus)QtCore.QMetaObject.connectSlotsByName(NodeStatus)def retranslateUi(self, NodeStatus):_translate = QtCore.QCoreApplication.translateNodeStatus.setWindowTitle(_translate("NodeStatus", "节点状态"))from pyqtgraph.opengl import GLViewWidget
      
    • 主文件中画图进程类和子窗口(显示3d散点图)类
    • from PyQt5.QtWidgets import QApplication, QMainWindow, QDialog
      from PyQt5.QtCore import QThread, pyqtSignal, QTimer, Qt
      from PyQt5 import uic
      import pyqtgraph.opengl as gl
      import numpy as npclass PlotNode(QThread):'''给予画图多线程提供点数据分析功能'''signal = pyqtSignal(object, object, object, object)  # 定义信号,根据信息交互设置参数位def __init__(self):super(PlotNode, self).__init__()self.nodeStatus = {}def plotNodeStatus(self):'''初始化画散点图所需的点数据:position,size,color:return:'''self.distance = 0  # 用于3D图的视角高度设定self.num = self.nodeStatus['num_nodes']self.x = self.nodeStatus['x']self.y = self.nodeStatus['y']self.z = self.nodeStatus['z']self.running = self.nodeStatus['running']self.malicious = self.nodeStatus['malicious']# 设置numpy.ndarray类型的数据,用于画散点图self.pos = np.empty((self.num, 3))self.size = np.empty((self.num))self.color = np.empty((self.num, 4))for i in range(self.num):self.pos[i] = (self.x[i], self.y[i], self.z[i])max_num = max(self.x[i], self.y[i], self.z[i])if abs(self.distance) < abs(max_num):self.distance = abs(max_num)self.size[i] = 0.5if self.running[i] == True and self.malicious[i] == False:self.color[i] = (0.0, 1.0, 0.0, 0.5)  # 绿色elif self.malicious[i] == True:self.color[i] = (1.0, 0.0, 0.0, 0.5)  # 红色else:self.color[i] = (1, 1, 1, 0.5)  # 灰色QThread.msleep(100)  # 等待100毫秒def run(self):for _ in range(300):self.plotNodeStatus()self.signal.emit(self.distance, self.pos, self.size, self.color)  # 向连接槽发射信号 self.yclass ChildWinNodeStatus(QDialog, Ui_NodeStatus):def __init__(self):super(ChildWinNodeStatus, self).__init__()self.setupUi(self)# 设置窗口最小化与最大化按钮self.setWindowFlags(Qt.Window)def child_plotNode(self, distance, pos, size, color):self.guiplot.clear()g = gl.GLGridItem()size_axes = distance * 3g.setSize(x=size_axes, y=size_axes, z=size_axes)self.guiplot.addItem(g)sp = gl.GLScatterPlotItem(pos=pos, size=size, color=color, pxMode=False)self.guiplot.addItem(sp)

       

  • 子窗口与父窗口信息交互

    • 建议写好子窗口的相关功能,在父窗口中对子窗口的内容进行相关操作。
    • 相关资料:
      • https://blog.csdn.net/API1_7/article/details/98249965(PyQt/PySide2 中的 信号与槽 (pyqtSignal/Signal) 、多线程 (QThread) 和 定时器 (Timer))
      • https://github.com/binghan523/pyqt_fatherAndChildSignalCommunication/tree/master/pyqt_fatherAndChildSignalCommunication/pyqt_fatherAndChildSignalCommunication(子窗口与父窗口之间互相发送接收消息)
    • 重点知识:
      • 类与类之间信息触发采用pyqtsignal,且注意设置的参数个数与要传的参内容一致。signal.connect(func)绑定信号发送后触发的函数
      • from PyQt5.QtCore import pyqtSignalsignal = pyqtSignal(object, object, object, object)  # 定义信号,根据信息交互设置参数位,objetct是通用格式# 主窗口中某函数,绑定def ui_plotStatus_child(self, nodeStatus):'''接收到节点数据后,在子窗口上画图'''self.plot_thread.nodeStatus = nodeStatusself.plot_thread.signal.connect(self.ChildUI_NodeStatus.child_plotNode)self.plot_thread.start()# self.plot_thread是在主窗口中提前实例化的PlotNode类对象

         

      • 在父窗口中,要先初始化一个子窗口的实例,当要打开子窗口时,让实例.show()即可
      • self.ChildUI_NodeStatus = ChildWinNodeStatus()self.ChildUI_NodeStatus.show()

         

      • 在主窗口的函数中对子窗口实例进行操作。
  • 常见问题解决方法

    • 若某按钮被点击动作为打开新的子窗口,且该按钮cliced绑定函数A,若在A函数外调用窗口.show()方法,UI会卡死。
      • 解决:当需要在A函数外打开该子窗口,则可写一句该button.clicked(),即相当于按钮被点击。不会卡死。

 

pyqt5开发过程关键问题总结


[点击查看](https://blog.csdn.net/qq_38025771/article/details/109675990)

 

 

 

 

 

 

 

 

 

 

 

 

这篇关于(详细分析)python PyQt5图形界面编程(含pyqtgraph画3D散点图、父子窗口间传递信息、pyinstaller打包可执行exe文件)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/180741

相关文章

Python的Darts库实现时间序列预测

《Python的Darts库实现时间序列预测》Darts一个集统计、机器学习与深度学习模型于一体的Python时间序列预测库,本文主要介绍了Python的Darts库实现时间序列预测,感兴趣的可以了解... 目录目录一、什么是 Darts?二、安装与基本配置安装 Darts导入基础模块三、时间序列数据结构与

Python正则表达式匹配和替换的操作指南

《Python正则表达式匹配和替换的操作指南》正则表达式是处理文本的强大工具,Python通过re模块提供了完整的正则表达式功能,本文将通过代码示例详细介绍Python中的正则匹配和替换操作,需要的朋... 目录基础语法导入re模块基本元字符常用匹配方法1. re.match() - 从字符串开头匹配2.

Python使用FastAPI实现大文件分片上传与断点续传功能

《Python使用FastAPI实现大文件分片上传与断点续传功能》大文件直传常遇到超时、网络抖动失败、失败后只能重传的问题,分片上传+断点续传可以把大文件拆成若干小块逐个上传,并在中断后从已完成分片继... 目录一、接口设计二、服务端实现(FastAPI)2.1 运行环境2.2 目录结构建议2.3 serv

通过Docker容器部署Python环境的全流程

《通过Docker容器部署Python环境的全流程》在现代化开发流程中,Docker因其轻量化、环境隔离和跨平台一致性的特性,已成为部署Python应用的标准工具,本文将详细演示如何通过Docker容... 目录引言一、docker与python的协同优势二、核心步骤详解三、进阶配置技巧四、生产环境最佳实践

Python一次性将指定版本所有包上传PyPI镜像解决方案

《Python一次性将指定版本所有包上传PyPI镜像解决方案》本文主要介绍了一个安全、完整、可离线部署的解决方案,用于一次性准备指定Python版本的所有包,然后导出到内网环境,感兴趣的小伙伴可以跟随... 目录为什么需要这个方案完整解决方案1. 项目目录结构2. 创建智能下载脚本3. 创建包清单生成脚本4

MySQL的JDBC编程详解

《MySQL的JDBC编程详解》:本文主要介绍MySQL的JDBC编程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言一、前置知识1. 引入依赖2. 认识 url二、JDBC 操作流程1. JDBC 的写操作2. JDBC 的读操作总结前言本文介绍了mysq

Python实现Excel批量样式修改器(附完整代码)

《Python实现Excel批量样式修改器(附完整代码)》这篇文章主要为大家详细介绍了如何使用Python实现一个Excel批量样式修改器,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一... 目录前言功能特性核心功能界面特性系统要求安装说明使用指南基本操作流程高级功能技术实现核心技术栈关键函

python获取指定名字的程序的文件路径的两种方法

《python获取指定名字的程序的文件路径的两种方法》本文主要介绍了python获取指定名字的程序的文件路径的两种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 最近在做项目,需要用到给定一个程序名字就可以自动获取到这个程序在Windows系统下的绝对路径,以下

使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解

《使用Python批量将.ncm格式的音频文件转换为.mp3格式的实战详解》本文详细介绍了如何使用Python通过ncmdump工具批量将.ncm音频转换为.mp3的步骤,包括安装、配置ffmpeg环... 目录1. 前言2. 安装 ncmdump3. 实现 .ncm 转 .mp34. 执行过程5. 执行结

Python实现批量CSV转Excel的高性能处理方案

《Python实现批量CSV转Excel的高性能处理方案》在日常办公中,我们经常需要将CSV格式的数据转换为Excel文件,本文将介绍一个基于Python的高性能解决方案,感兴趣的小伙伴可以跟随小编一... 目录一、场景需求二、技术方案三、核心代码四、批量处理方案五、性能优化六、使用示例完整代码七、小结一、