筱团Blog筱团のBlog

PyQt6 / PySide6

筱团·2023-02-23 15:14·6123 次阅读

PyQt6 / PySide6

Prerequisite#

Qt 是 C++ 写的图形界面工具,PyQt 和 PySide 都是 Qt 的儿子
PyQt5 和 PyQt6,一家私人公司开发的,用它开发商用软件要给这家公司交钱,不交钱就吃官司(PyQt6 版本是 PyQt5 版本的升级替代者)
PySide2 和 PySide6,分别是基于 C++ 下的 Qt5 和 Qt6 开发的,用它写商用软件是允许的,不会吃官司(PySide6 版本是 PySide2 版本的升级替代者)

总结:PySide6 和 PyQt6 基本类似,只用学 PySide6 就行
PS:我之所以学 Python 版本的 GUI 是因为要完成一个《基于人工智能的图片动漫化》的项目,简单来讲就是 Python UI 界面 + 人工智能 API

入门准备#

视频教程为:

参考文档为:

参考项目#

针对部分类似目标的成品进行考察(主要参考外观设计结合人工智能 API 的方式

一、跟着教程学习 PySide6#

项目介绍#

视频:Learn Python GUI Development for Desktop – PySide6 and Qt Tutorial
知识总结:Pyside6 用法、QT designer 用法

下载#

QTWidgets 代码#

大多数写法如下,这套模板非常简约,下面是 main.py 文件,还有一个控件文件

Copy
import sys from PySide6.QtWidgets import QApplication # 自定义类 from button_holder import ButtonHolder app = QApplication(sys.argv) window = XXX() window.show() app.exec()

PS:大致看一两个控件的演示,就亲自运行文件中的全部代码看效果(不要求记住代码,有个印象即可),然后直接跳到 3:52:00 看下一章节

QtDesigner#

制作 ui 文件使用的软件:QtDesigner

编译 ui 文件至 python 文件命令:pyside6-uic widget.ui > ui_widget.py,记得更改文件为 UTF-8
编译资源文件至 python 文件命令:pyside6-rcc resource.qrc -o resource_rc.py

关于 widget 文件(UI 控件)的模板
文件中有六个文件
名称是:main.pywidget.pywidget.uiresource.qrcresource_rc.pyui_widget.py
需要写代码的:主文件(main.py)、控件文件(widget.py
在 QtDesigner 中操作的:UI 控件(widget.ui)、资源文件(resource.qrc

Copy
from PySide6.QtCore import Qt from PySide6.QtWidgets import QWidget # UI 文件、资源文件 from ui_widget import Ui_Widget import resource_rc class Widget(QWidget, Ui_Widget): def __init__(self): super().__init__() self.setupUi(self) self.setWindowTitle("User data")

最后#

再把项目文件中的演示全都运行一遍即可

二、初步体验实战项目#

项目介绍#

视频:Python+Pyside/PyQt实现的GUI桌面应用
博客:Python系列-GUI-pyqt(pyside6)
Github 项目:PyDracula - Modern GUI PySide6 / PyQt6
环境:Python 10 + PySide6
目的:在已有的项目上,进行改造和功能实现

项目结构#

  • main.py: 主文件
  • main.ui: Qt Designer 工程文件
  • resouces.qrc: Qt Designer 资源文件
  • setup.py: 编译应用程序
  • themes/: 主题文件
  • modules/: GUI 的各个模块
  • modules/app_funtions.py: 应用功能函数
  • modules/app_settings.py: 用于配置用户界面的全局变量。
  • modules/resources_rc.py: 使用命令为 python 编译的 resource.qrc 文件(pyside6-rcc resources.qrc -o resources_rc.py
  • modules/ui_functions.py: 与用户界面 GUI 相关的函数
  • modules/ui_main.py: 与 Qt Designer 导出的用户界面相关的文件
  • images/: 所有图像和图标

初步改造#

  • 作者和版本号:modules/ui_main.py 最后两行
  • 软件标题:main.py 的 title 和 description 同时修改(其实有作用的是后者)
  • 图片:images/,记得修改后的文件名不能变
  • 按钮功能禁用:main.pybtnName == "btn_save" 后面删除 print,接上 QMessageBox.information(self, "提示", "该功能暂未实现", QMessageBox.Yes)

全部修改完成后,运行 pyside6-rcc resources.qrc -o resources_rc.py,再将 resources_rc.py 从最外层拷贝到 modules/

实现功能:切换黑白主题#

  1. 主题初始化
Copy
# 路径冻结,防止打包成 exe 后路径错乱 if getattr(sys, 'frozen', False): absPath = os.path.dirname(os.path.abspath(sys.executable)) elif __file__: absPath = os.path.dirname(os.path.abspath(__file__)) # 主题初始化为白色 useCustomTheme = True self.useCustomTheme = useCustomTheme self.absPath = absPath themeFile = os.path.abspath(os.path.join(absPath, "themes\py_dracula_light.qss"))
  1. 按钮添加功能
Copy
# 新增功能:切换皮肤 widgets.btn_message.clicked.connect(self.buttonClick)
  1. 实现具体切换主题的功能
Copy
# 切换主题 if btnName == "btn_message": if self.useCustomTheme: themeFile = os.path.abspath(os.path.join(self.absPath, "themes\py_dracula_dark.qss")) # 跟着原先的代码走 UIFunctions.theme(self, themeFile, True) AppFunctions.setThemeHack(self) self.useCustomTheme = False else: themeFile = os.path.abspath(os.path.join(self.absPath, "themes\py_dracula_light.qss")) # 跟着原先的代码走 UIFunctions.theme(self, themeFile, True) AppFunctions.setThemeHack(self) self.useCustomTheme = True

实现功能:实时监控(电脑资源,如 cpu、内存)#

BUG:点击绘图按钮后,再点击清除,终端会显示 "Can not add series. Series already on the chart.",我认为是 self.chart.addSeries(self.seriesS) 代码的问题,日后待修改

  1. 在 QtDesigner 中创建新按钮和新页面
  • main.ui 一般导入 QtDesigner 后,预览 python 代码,直接粘贴到 ui_main.py(节省了用命令转换)
  • QtDesigner 中按 Ctrl + R 预览

使用的控件是 Push Button 和 Graphics View,记得 Graphics View 要权限提升(QChartView),完成后 Ctrl + s 保存,再回到 main.py 中添加代码

Copy
# 新增功能:电脑信息数据分析 widgets.btn_computer.clicked.connect(self.buttonClick) widgets.computer_info_start.clicked.connect(self.start_computer_info) widgets.computer_info_clear.clicked.connect(self.clear_computer_info) # 电脑信息数据分析 if btnName == "btn_computer": widgets.stackedWidget.setCurrentWidget(widgets.computer_info) # SET PAGE UIFunctions.resetStyle(self, btnName) # RESET ANOTHERS BUTTONS SELECTED btn.setStyleSheet(UIFunctions.selectMenu(btn.styleSheet())) # SELECT MENU self.seriesS = QLineSeries() self.seriesL = QLineSeries() self.seriesS.setName("cpu") self.seriesL.setName("memory")
  1. 自定义类
Copy
# 新增的类 import psutil import time from PySide6.QtCharts import QChart, QLineSeries class NewThread(QThread): # 自定义信号声明 # 使用自定义信号和 UI 主线程通讯,参数是发送信号时附带参数的数据类型,可以是 str,int,list 等 finishSignal = Signal(str) # 带一个参数 t def __init__(self, parent=None): super(NewThread, self).__init__(parent) # run 函数是子线程中的操作,线程启动后开始执行 if os.path.exists(f"./computer_info.csv"): pass else: with open(r"./computer_info.csv", "w") as f: pass def run(self): timer = 0 while True: timer += 1 cpu_percent = psutil.cpu_percent(interval=1) cpu_info = cpu_percent virtual_memory = psutil.virtual_memory() memory_percent = virtual_memory.percent with open(r"./computer_info.csv", "a") as f: f.write(f"{timer},{cpu_info}{memory_percent}\n") time.sleep(1) # 发射自定义信号 # 通过 emit 函数将参数 i 传递给主线程,触发自定义信号 self.finishSignal.emit("1")
  1. 自定义函数
Copy
def start_computer_info(self): """ 开始获取电脑数据 """ # 开始分析记录电脑数据,需要持续获取,然后分析 self.thread1 = NewThread() # 实例化一个线程 # 将线程 thread 的信号 finishSignal 和 UI 主线程中的槽函数 data_display 进行连接 self.thread1.finishSignal.connect(self.data_display) # 启动线程,执行线程类中的 run 函数 self.thread1.start() def data_display(self, str_): """ 电脑信息的数据展示 """ # 获取已经记录好的数据并展示 # 设置一个 flag with open(r"./computer_info.csv", "r") as f: reader = f.readlines() reader_last = reader[-1].replace("\n", "").split(",") # 横坐标 col = int(reader_last[0]) # cpu cpu = float(reader_last[1]) # 内存 memory = float(reader_last[2]) self.seriesS.append(col, cpu) self.seriesL.append(col, memory) self.chart = QChart() self.chart.setTitle("设备资源图") self.chart.addSeries(self.seriesS) self.chart.addSeries(self.seriesL) self.chart.createDefaultAxes() widgets.graphicsView.setChart(self.chart) def clear_computer_info(self): """ 清除设备表格信息 """ self.seriesS.clear() self.seriesL.clear() self.chart.addSeries(self.seriesS) self.chart.addSeries(self.seriesL)

实现功能:打开本地文件+打开外部网址+随机切换本地图片#

  1. 在 QtDesigner 中创建新按钮
  2. main.py 中添加功能
Copy
# 新增功能:打开本地文件 widgets.btn_local.clicked.connect(self.open_file) # 新增功能:打开网站 widgets.btn_web.clicked.connect(self.open_web) # 新增功能:切换图片 widgets.btn_pic.clicked.connect(self.change_pic) def open_file(self): import webbrowser webbrowser.open("说明书" + ".docx") def open_web(self): import webbrowser webbrowser.open("www.baidu.com") def change_pic(self): url_list = [ "./1.jpg", "./2.jpg", "./3.jpg", "./4.jpg", "./5.png" ] import random index = random.randint(0, 4) # 很神奇,能显示 5 张图片 lb1 = widgets.label # 同页面下的控件 pix = QPixmap(url_list[index]).scaled(lb1.size(), aspectMode=Qt.KeepAspectRatio) lb1.setPixmap(pix) lb1.repaint()

打包#

  • 下载打包库:pip install pyinstaller
  • 一个 exe(但需要静态资源),缺点是启动慢 pyinstaller -F .\main.py
  • 一个 exe + 多个文件(依然需要静态资源),缺点是文件多 pyinstaller -D .\main.py

完结撒花,全部代码都放在这里#

posted @   筱团  阅读(6126)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
点击右上角即可分享
微信分享提示
目录