PySide环境配置及工具使用

发布于:2025-06-24 ⋅ 阅读:(20) ⋅ 点赞:(0)

1 概述

通常提到的 PyQt 实际上可以分为 PyQtPySide 两个分支。

PyQt6PySide6 都是基于 Qt 库开发的 Python 绑定,用于构建跨平台的图形用户界面(GUI)应用程序。它们在功能上非常相似,主要区别体现在授权方式、维护团队以及部分 API 设计上。

本文重点介绍通用 PySide 的环境配置、工具配置及使用方法,适用于在线、离线配置,兼容多个常用版本。

  • PySide 环境配置 是进行 PySide 开发的第一步,虽然基础但至关重要。
  • 在实际开发中,工具的使用 对开发效率影响较大。
  • 与 Qt 官方安装包“开箱即用”的体验不同,PySide 相对较新,存在较多版本差异和 bug,因此本文将总结以下内容:
    • 常用版本的环境搭建
    • 工具配置与使用技巧
    • 常见问题与 bug 的解决方案
  • 主要版本:
    • PySide2:基于 Qt 5(>=5.11);
    • PySide6:基于 Qt 6,是当前推荐使用的版本;

1.1 PySide 能做什么?

  1. 图形用户界面开发:使用 Qt 提供的 QWidget 或 QML 模块构建桌面应用程序界面。
  2. 跨平台支持:支持 Windows、macOS、Linux 等主流操作系统。
  3. 多媒体和网络功能:内置模块支持音视频播放、网络通信(如 HTTP 请求、WebSocket)等功能。
  4. 数据可视化:利用 Qt Charts、QOpenGLWidget 等模块实现图表展示和 3D 渲染。
  5. 嵌入式系统开发:可用于开发嵌入式设备的 UI,如工业控制面板、车载系统等。
  6. 与 Web 技术集成:使用 Qt WebEngine 模块可以嵌入网页内容或开发混合型应用。

1.2 PySide 的优点

优点 描述
🌐 跨平台 支持 Windows、Linux、macOS,甚至嵌入式系统。
📦 功能丰富 提供 GUI、网络、数据库、多线程、绘图等一整套模块。
🔧 官方支持 PySide 是 Qt 官方提供的 Python 绑定,更新及时、文档完善。
🚀 性能较好 基于 C++ 的 Qt 引擎,性能优于 Tkinter 等纯 Python GUI 框架。
📐 支持 QML 可以结合 QML 进行现代 UI 设计,适合动态界面。

1.3 PySide 的缺点

缺点 描述
⚖️ 许可证复杂 商业用途需要购买 Qt 许可证;开源项目可用 LGPL 协议。
📦 包体积较大 打包发布时依赖较多,最终程序体积较大。
🧠 学习曲线陡峭 Qt API 复杂,对新手有一定门槛,尤其是布局管理、信号槽机制等。
📱 移动端支持有限 虽然支持 Android/iOS,但不如原生开发或 Flutter/Kivy 成熟。

1.4 示例代码(简单窗口)

from PySide6.QtWidgets import QApplication, QLabel, QWidget, QVBoxLayout # 导入必要的模块

app = QApplication([]) # 创建一个QApplication实例,这是所有PySide6应用程序的基础
w = QWidget() # 创建主窗口部件(QWidget),它将作为应用程序的主窗口
label = QLabel("Hello, PySide6!", w) # 创建一个标签控件(QLabel),显示文本 "Hello, PySide6!"

w.show() # 显示主窗口

app.exec() # 进入应用程序的主循环,等待用户交互

在这里插入图片描述


2 环境准备

2.1 安装必要软件

  1. Python:从 Python 官方网站 下载并安装。
  2. PyCharm:从 PyCharm 官方网站 下载并安装。
  3. Qt(可选):从 Qt 官方下载页面 下载并安装。虽然可以在 Qt Creator 中开发 PyQt 项目,但 PyCharm 对 Python 语法的支持更好。

2.2 修改 pip 源

为避免默认源安装速度过慢,建议使用 阿里云 pip 镜像。按以下步骤操作,如果不存在则创建:

  1. Windows系统:C:\Users\用户名\.pip\pip.conf
  2. Linux系统:~/.pip/pip.conf
  3. .pip 文件夹中创建一个 pip.conf 文件,并添加以下内容:
[global]
index-url = http://mirrors.aliyun.com/pypi/simple/

[install]
trusted-host=mirrors.aliyun.com

3 PySide2

3.1 环境要求

支持环境

环境 版本
PySide2 python2.7、3.5<=python<=3.10
系统 win7+、linux、MacOS

演示环境

环境 版本
PySide2 PySide2=5.15.2.1
python V3.8.10
系统 windows10
pycharm pycharm-community-2024.3.5.exe

3.2 配置PySide2

方法1: 命令行安装(在线)

  • 使用pip install pyside2安装最新版本(网络状况差可能导致安装失败);
  • 使用pip install pyside2==5.15.2.1指定安装版本(网络状况差可能导致安装失败);
  • 使用pip install PySide2 --index-url https://mirrors.aliyun.com/pypi/simple 指定临时安装源进行安装;
  • 使用pip install https://download.qt.io/official_releases/QtForPython/pyside2/PySide2-5.15.2.1-5.15.2-cp35.cp36.cp37.cp38.cp39.cp310-none-win_amd64.whl指定下载地址进行安装;

方法2: 下载whl包安装(离线)

方法3: 使用pycharm安装(在线)

  • 打开pycharm,创建一个工程;

  • 选择python软件包,搜索PySide2,如下所示,点击【安装】;

    在这里插入图片描述


3.3 工具配置

pyside2或者pyside6<6.5的版本,内置工具不多,只有designer、lupdate、rcc、uic等几个;

如果需要用到其他工具,可以单独安装Qt安装包或者高版本的PySide6;

  • 安装完成PySide2后,打开pycharm,【文件】【设置】【工具】【外部工具】;

  • 点击+,如下所示配置pyside2-designer工具;

    在这里插入图片描述

  • 配置完成后,点击【工具】【外部工具】就可以打开UI设计器。

    在这里插入图片描述

  • 使用pyproject文件管理工程是一个更加简便的方式,但是只有在PySide6.5以上版本才支持,这里通过自己编写脚本,可以通过pyproject文件对工程进行管理,简化部分操作;

  • 在工程顶级路径下创建一个project.py文件;

  • 添加章节6脚本,运行脚本代码可自动执行重复操作,简化开发流程,避免出现基础错误。


4 PySide6

4.1 环境

支持环境

环境 版本
PySide6 3.9<=python
系统 win10+、linux、MacOS
支持win7系统 python3.8 + PySide6.1.3

演示环境

环境 版本
PySide6 PySide6=6.8.3
python V3.13.3
系统 windows10
pycharm pycharm-community-2024.3.5.exe

4.2 配置PySide6

安装方法1:使用命令行在线安装

  • 使用pip install PySide6目录安装默认版本;

  • 使用pip install pyside6==6.8.3安装指定版本;

  • 使用pip install PySide6 --index-url https://mirrors.aliyun.com/pypi/simple 指定安装源进行安装;

  • 使用pip install https://download.qt.io/official_releases/QtForPython/pyside6-essentials/PySide6_Essentials-6.8.2.1-cp39-abi3-win_amd64.whl指定下载地址进行安装;

  • 使用pip install --index-url=https://download.qt.io/snapshots/ci/pyside/6.4/latest pyside6 --trusted-host download.qt.io从指定服务器安装。

安装方法2: 使用pycharm安装

  • 打开pycharm,创建一个工程;

  • 选择python软件包,搜索PySide6,如下所示,点击【安装】;

    在这里插入图片描述

安装方法3: 下载whl安装包,离线安装,对于离线环境或者网络不好pip安装失败的环境可用;


4.3 工具配置

  1. 打开【设置】【工具】【外部工具】,点击+;

  2. 添加designer,设置程序路径工作目录如下所示;

    在这里插入图片描述

  3. 添加pyside6-project,用于构建pyside工程;

    在这里插入图片描述

  4. 更新翻译文件(ts)

    在这里插入图片描述

  5. 打开翻译文件pyside6-linguist

    在这里插入图片描述


4.4 修改pyside6-project lupdate的bug

  • 使用 pyside6-project lupdate 命令可以在 PySide6 中生成翻译使用的 ts 文件,但存在一些问题:

    • 无法将 ts 文件放在子文件夹下。
    • 无法清除已经失效的文本。
  • 这是因为 pyside6-project lupdate 中使用的是 ts 文件名,不包含路径,所以会在工程路径下执行,并且有几个 ts 文件就会执行几次。

  • 解决办法:打开 .venv\Lib\site-packages\PySide6\scripts\project.py 文件,在 def lupdate(self) 函数中修改为以下代码:

    def lupdate(self):
        for sub_project_file in self.project.sub_projects_files:
            Project(project_file=sub_project_file).lupdate()
    
        if not self.project.ts_files:
            print(f"{self.project.project_file.name}: No .ts file found.",
                  file=sys.stderr)
            return
    
        source_files = self.project.python_files + self.project.ui_files
        project_dir = self.project.project_file.parent
        cmd_prefix = [LUPDATE_CMD] + [os.fspath(p.relative_to(project_dir)) for p in source_files]
        cmd_prefix.append("-ts")
        ts_files = []
        for ts_file in self.project.ts_files:
            if requires_rebuild(source_files, ts_file):
                ts_dir = ts_file.parent
                if not ts_dir.exists():
                    ts_dir.mkdir(parents=True, exist_ok=True)
                ts_files.append(ts_file.resolve().as_posix())
        if ts_files:
            cmd = cmd_prefix;
            cmd.extend(ts_files)
            cmd.append("-no-obsolete") # 清除失效文本
            run_command(cmd, cwd=project_dir)
    
  • 修改后,运行 pyside6-project.exe lupdate 命令就会将 ts 文件生成到指定路径中,并且只执行一次。

    (.venv) PS E:\Code\py\Test> pyside6-project.exe lupdate
    pyside6-lupdate main.py mainwindow.py TableWidget.py mainwindow.ui logwidget.ui control.ui -ts E:/Code/py/Test/Language/Test_zh_CN.ts E:/Code/py/Test/Language/Test_en_US.ts
    

5 工具使用

5.1 使用pyside6-project构建工程

  1. 需要pyside6.5以上版本支持,低版本可以通过自定义脚本支持(见后续章节);

  2. 创建一个名称.pyproject文件;

  3. 按以下格式添加需要构建的文件名称,会批量将 ui 文件生成 ui_name.py 文件:

    {
        "files": [
            "main.py",
            "widget.ui",
            "widget1.ui"
        ]
    }
    
  4. 运行python project.py -o 命令,自动将所有文件加载到.pyproject工程文件进行管理;

  5. 鼠标点击【工具】【外部工具】【pyside6-project】,完成工程构建;

    • 将ui、qrc文件生成为py文件;

    • .ts翻译文件编译为.qm文件;

    在这里插入图片描述

  6. 注意:pyside6-project需要tomlkit库支持。


5.2 创建、打开ui文件

  1. 鼠标点击【工具】【外部工具】【pyside6-designer】,打开设计师窗口;

    在这里插入图片描述

  2. 选择创建窗体类型,点击【创建】

    在这里插入图片描述

  3. 创建完成后,按【Ctrl + S】将ui文件保存到工程文件夹中;

  4. 创建完成后在pycharm中就可以看见ui文件了,双击ui文件就可以使用设计器打开;

    在这里插入图片描述


5.3 生成翻译文件

  1. 生成pyproject工程文件;

  2. 打开.pyproject工程文件,添加生成.ts翻译文件的路径;

    {
        "files": [
            "main.py",
            "res/res.qrc",
            "res/language/en_US.ts",
            "res/language/zh_CN.ts",
        ]
    }
    
  3. 鼠标点击【工具】【外部工具】【lupdate】,自动将代码中需要翻译的文本输出到.ts文件,如果ts文件不存在则会自动创建,如果已存在则会更新;

  4. 如果是小于PySide6.5版本,则使用自定义脚本命令python project.py -lupdate


5.4 修改ts翻译文件

  1. 使用lupdate生成.ts文件;

  2. 鼠标选中.ts文件,右键【外部工具】【pyside6-linguist】,打开Qt语言家

    在这里插入图片描述

  3. Qt语言家窗口中可将文本翻译为指定语言。

    在这里插入图片描述


6 工程管理脚本

  • 输入python project.py -h 查看脚本使用方法。

    在这里插入图片描述

"""
这个文件是用来搜索当前路径下所有py、ui、qrc、ts文件,并生成pyproject文件。
不再需要手动谢pyproject文件,只需要运行这个文件即可。
支持自动执行 Qt 用户界面编译器(uic)和 Qt 资源编译器(rcc);
支持自动执行 Qt 语言文件更新工具(lupdate);
"""
import fnmatch
import json
import os
import subprocess
from pathlib import Path  # 更安全的路径处理
import importlib.util
import argparse
import sys

def list_files(directory='.', include_patterns=None, exclude_patterns=None, ignore_folders=None):
    """
    列出指定目录下所有匹配指定模式的文件
    :param directory:        查询目录
    :param include_patterns: 搜索的文件,支持通配符
    :param exclude_patterns: 需要排除的文件,支持通配符
    :param ignore_folders:   需要忽略的文件夹
    :return: 匹配的文件列表,JSON 格式,输出为pyproject文件可用格式
    """
    if include_patterns is None:
        include_patterns = {'*.py', '*.ui', '*.qrc', '*.ts'}
    if exclude_patterns is None:
        exclude_patterns = set()
    if ignore_folders is None:
        ignore_folders = set()

    files_list = []
    for root, dirs, files in os.walk(directory):
        # 过滤需要忽略的文件夹
        dirs[:] = [d for d in dirs if d not in ignore_folders]
        for file in files:
            # 检查文件是否匹配需要包含的通配符模式,并且不匹配需要排除的通配符模式
            if any(fnmatch.fnmatch(file, pattern) for pattern in include_patterns) and \
               not any(fnmatch.fnmatch(file, pattern) for pattern in exclude_patterns):
                # 计算相对路径
                relative_path = os.path.relpath(os.path.join(root, file), directory)
                relative_path = relative_path.replace('\\', '/')
                files_list.append(relative_path)

    # 返回 JSON 格式的文件列表
    return json.dumps({"files": files_list}, indent=4)


def run_uic(project_name=None):
    """
    执行 Qt 用户界面编译器(uic)的自动化流程

    ▼ 典型工作流程:
    1. 定位 Qt 用户界面编译器(uic)
    2. 加载项目配置文件(JSON格式)
    3. 遍历配置文件中的 ui 文件路径
    4. 构建 uic 命令行参数
    5. 执行命令并处理执行结果,将ui文件编译为py文件
    """
    project_file = Path(project_name).resolve()

    with open(project_file, 'r', encoding='utf-8') as f:
        config = json.load(f)
        # ▼ 配置有效性验证
        if 'files' not in config or not isinstance(config['files'], list):
            raise ValueError("配置文件必须包含 'files' 列表")
        ui_files = [Path(f).resolve() for f in config["files"] if f.endswith('.ui')]
        for ui_file in ui_files:
            filename = os.path.basename(ui_file)
            parent_dir = os.path.dirname(ui_file)
            out_file = os.path.join(parent_dir, 'ui_' + filename.replace('.ui', '.py'))
            if importlib.util.find_spec('PySide6') is not None: # 优先使用 PySide6, 如果找不到则使用 PySide2
                cmd_args = ['pyside6-uic', str(ui_file), '-o', out_file]
            elif importlib.util.find_spec('PySide2') is not None:
                cmd_args = ['pyside2-uic', str(ui_file), '-o', out_file]
            result = subprocess.run(
                cmd_args,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                check=True
            )
            print(f"执行命令: {result.args}")

def run_rcc(project_name=None):
    """
    执行 Qt 资源编译器(rcc)的自动化流程
    ▼ 典型工作流程:
    1. 定位 Qt 资源编译器(rcc)
    2. 加载项目配置文件(JSON格式)
    3. 遍历配置文件中的 qrc 文件路径
    4. 构建 rcc 命令行参数
    5. 执行命令并处理执行结果,将qrc文件编译为py文件
    """
    project_file = Path(project_name).resolve()

    with open(project_file, 'r', encoding='utf-8') as f:
        config = json.load(f)
        # ▼ 配置有效性验证
        if 'files' not in config or not isinstance(config['files'], list):
            raise ValueError("配置文件必须包含 'files' 列表")
        rc_files = [Path(f).resolve() for f in config["files"] if f.endswith('.qrc')]
        for rc_file in rc_files:
            filename = os.path.basename(rc_file)
            parent_dir = os.path.dirname(rc_file)
            out_file = os.path.join(parent_dir, 'rc_' + filename.replace('.qrc', '.py'))
            if importlib.util.find_spec('PySide6') is not None:
                cmd_args = ['pyside6-rcc', str(rc_file), '-o', out_file]
            elif  importlib.util.find_spec('PySide2') is not None:
                cmd_args = ['pyside2-rcc', str(rc_file), '-o', out_file]
            result = subprocess.run(
                cmd_args,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
                check=True
            )
            print(f"执行命令: {result.args}")

def run_lupdate(project_name=None):
    """
    执行 Qt 语言文件更新工具(lupdate)的自动化流程

    ▼ 典型工作流程:
    1. 定位 Qt 语言更新工具(lupdate)
    2. 加载项目配置文件(JSON格式)
    3. 构建 lupdate 命令行参数
    4. 执行命令并处理执行结果

    ▼ 配置文件要求:
    - 必须包含 'files' 键,值为文件路径列表
    - 示例配置:
      {
          "files": [
              "src/*.py",
              "translations/zh_CN.ts",
              "translations/en_US.ts"
          ]
      }

    异常:
        ValueError: 当配置文件格式无效时抛出
    """
    # 初始化路径对象(使用 pathlib 处理跨平台路径问题)
    # language: PySide6 语言更新工具的可执行路径
    # project_file: 项目配置文件路径(包含待翻译文件列表)
    # ts_files: 生成的翻译文件目标路径列表(中英文版本)
    if importlib.util.find_spec('PySide6') is not None:
        lupdate = Path('pyside6-lupdate.exe').resolve() # lupdate 工具路径,如果不存在,请手动修改路径
        # 构建基础命令参数(使用字符串显式转换保证兼容性)
        cmd_args = [str(lupdate), '-no-obsolete'] # -no-obsolete 选项用于排除已过时的翻译
    elif importlib.util.find_spec('PySide2') is not None:
        lupdate = Path('pyside2-lupdate.exe').resolve() # lupdate 工具路径,如果不存在,请手动修改路径
        # 构建基础命令参数(使用字符串显式转换保证兼容性)
        cmd_args = [str(lupdate), '-noobsolete']
    project_file = Path(project_name).resolve()


    try:
        # 读取并解析项目配置文件(JSON 格式)
        # 将配置中的文件列表添加到命令参数中
        with open(project_file, 'r', encoding='utf-8') as f:
            config = json.load(f)
            # ▼ 配置有效性验证
            if 'files' not in config or not isinstance(config['files'], list):
                raise ValueError("配置文件必须包含 'files' 列表")
            # 过滤掉以 .ts 为后缀的文件
            filtered_files = [file for file in config['files'] if not file.endswith('.ts')]
            cmd_args.extend(filtered_files)  # 直接扩展参数列表
            # 从文件列表中筛选出以 .ts 结尾的文件路径
            # ts_files: 生成的翻译文件目标路径列表(中英文版本)
            ts_files = [Path(f).resolve() for f in config["files"] if f.endswith('.ts')]

            # ▼ 防止无翻译文件导致命令错误
            if not ts_files:
                print("警告:未发现.ts翻译文件")
                return

            # 添加翻译文件生成参数
            # -ts 参数后接转换后的字符串路径列表
            cmd_args.extend(['-ts', *map(str, ts_files)])

        # 执行外部命令并捕获输出
        # 使用 check=True 自动检查非零返回码
        # text=True 自动解码输出内容为字符串
        result = subprocess.run(
            cmd_args,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            text=True,
            check=True
        )
        print(f"执行命令: {' '.join(result.args)}")
        # ▼ 输出处理策略
        if result.stdout:
            print("输出日志:\n" + result.stdout)
        if result.stderr:
            print("错误信息:\n" + result.stderr)

    # ▼ 异常处理优先级调整
    except FileNotFoundError as e:
        print(f"关键文件缺失: {e.filename}")
    except json.JSONDecodeError as e:
        print(f"Json 解析错误: {project_file}: {e}")
    except subprocess.CalledProcessError as e:
        print(f"指令运行失败 (code {e.returncode}):\n{e.stderr}")
    except ValueError as e:
        print(f"配置验证失败: {e}")

def find_pyproject_files(directory='.'):
    pyproject_files = []
    for root, dirs, files in os.walk(directory):
        for file in files:
            if fnmatch.fnmatch(file, '*.pyproject'):
                pyproject_files.append(os.path.join(root, file))
    return pyproject_files

if __name__ == '__main__':
    # 1. 创建解析器
    parser = argparse.ArgumentParser(description='工程管理')
    # 2. 添加参数
    parser.add_argument('-o', '--output', action='store_true', help='自动遍历当前路径下所有py、ui、qrc、ts文件,并生成pyproject文件')
    parser.add_argument('-b', '--build', action='store_true', help='构建项目,使用pyproject文件生成ui、qrc文件的py文件')
    parser.add_argument('-u', '--lupdate', action='store_true', help='执行 Qt 语言文件更新工具(lupdate)')
    parser.add_argument('-p', '--pyproject', type=str, help='指定pyproject文件路径,如果不指定则使用当前路径下的pyproject文件')
    # 3. 解析参数
    args = parser.parse_args()

    # 获取pyproject文件路径
    pyproject_file = args.pyproject
    if not pyproject_file:
        pyprojects = find_pyproject_files()
        if pyprojects:
            pyproject_file = pyprojects[0]

    cmd_num = len(sys.argv) - 1
    if args.output or cmd_num == 0: # 使用-o  参数或者无参数时,执行输出
        # 列出当前路径下所有.py、.ui、.qrc、.ts文件,忽略.temp类型的文件和名为temp的文件夹
        ret = list_files(include_patterns={'*.py', '*.ui', '*.qrc', '*.ts'},
               exclude_patterns={'__init__.py', 'project.py', 'ui_*', 'rc_*'}, ignore_folders={'.venv'})
        if pyproject_file:
            with open(pyproject_file, 'w', encoding='utf-8') as project:
                project.write(ret)

    if args.build:
        if pyproject_file:
            # 可以选择不执行后面三个函数
            run_uic(pyproject_file) # 执行 Qt 用户界面编译器, 将ui文件编译为py文件
            run_rcc(pyproject_file) # 执行 Qt 资源编译器, 将qrc文件编译为py文件

    if args.lupdate:
        run_lupdate(pyproject_file) # 执行 Qt 语言文件更新工具(lupdate)


7 相关地址


网站公告

今日签到

点亮在社区的每一天
去签到