(详细分析)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的requests库调用API接口的详细步骤

《使用Python的requests库调用API接口的详细步骤》使用Python的requests库调用API接口是开发中最常用的方式之一,它简化了HTTP请求的处理流程,以下是详细步骤和实战示例,涵... 目录一、准备工作:安装 requests 库二、基本调用流程(以 RESTful API 为例)1.

Python清空Word段落样式的三种方法

《Python清空Word段落样式的三种方法》:本文主要介绍如何用python-docx库清空Word段落样式,提供三种方法:设置为Normal样式、清除直接格式、创建新Normal样式,注意需重... 目录方法一:直接设置段落样式为"Normal"方法二:清除所有直接格式设置方法三:创建新的Normal样

Python调用LibreOffice处理自动化文档的完整指南

《Python调用LibreOffice处理自动化文档的完整指南》在数字化转型的浪潮中,文档处理自动化已成为提升效率的关键,LibreOffice作为开源办公软件的佼佼者,其命令行功能结合Python... 目录引言一、环境搭建:三步构建自动化基石1. 安装LibreOffice与python2. 验证安装

把Python列表中的元素移动到开头的三种方法

《把Python列表中的元素移动到开头的三种方法》在Python编程中,我们经常需要对列表(list)进行操作,有时,我们希望将列表中的某个元素移动到最前面,使其成为第一项,本文给大家介绍了把Pyth... 目录一、查找删除插入法1. 找到元素的索引2. 移除元素3. 插入到列表开头二、使用列表切片(Lis

Python按照24个实用大方向精选的上千种工具库汇总整理

《Python按照24个实用大方向精选的上千种工具库汇总整理》本文整理了Python生态中近千个库,涵盖数据处理、图像处理、网络开发、Web框架、人工智能、科学计算、GUI工具、测试框架、环境管理等多... 目录1、数据处理文本处理特殊文本处理html/XML 解析文件处理配置文件处理文档相关日志管理日期和

Python标准库datetime模块日期和时间数据类型解读

《Python标准库datetime模块日期和时间数据类型解读》文章介绍Python中datetime模块的date、time、datetime类,用于处理日期、时间及日期时间结合体,通过属性获取时间... 目录Datetime常用类日期date类型使用时间 time 类型使用日期和时间的结合体–日期时间(

使用Python开发一个Ditto剪贴板数据导出工具

《使用Python开发一个Ditto剪贴板数据导出工具》在日常工作中,我们经常需要处理大量的剪贴板数据,下面将介绍如何使用Python的wxPython库开发一个图形化工具,实现从Ditto数据库中读... 目录前言运行结果项目需求分析技术选型核心功能实现1. Ditto数据库结构分析2. 数据库自动定位3

Python yield与yield from的简单使用方式

《Pythonyield与yieldfrom的简单使用方式》生成器通过yield定义,可在处理I/O时暂停执行并返回部分结果,待其他任务完成后继续,yieldfrom用于将一个生成器的值传递给另一... 目录python yield与yield from的使用代码结构总结Python yield与yield

python使用Akshare与Streamlit实现股票估值分析教程(图文代码)

《python使用Akshare与Streamlit实现股票估值分析教程(图文代码)》入职测试中的一道题,要求:从Akshare下载某一个股票近十年的财务报表包括,资产负债表,利润表,现金流量表,保存... 目录一、前言二、核心知识点梳理1、Akshare数据获取2、Pandas数据处理3、Matplotl

Django开发时如何避免频繁发送短信验证码(python图文代码)

《Django开发时如何避免频繁发送短信验证码(python图文代码)》Django开发时,为防止频繁发送验证码,后端需用Redis限制请求频率,结合管道技术提升效率,通过生产者消费者模式解耦业务逻辑... 目录避免频繁发送 验证码1. www.chinasem.cn避免频繁发送 验证码逻辑分析2. 避免频繁