PySide6-Advanced


前言:本文件涵盖范围

本章节专门用于收录 PySide6 开发中无法单纯归类到某个 QWidget 或 QLayout 下的“骨干机制”与“高阶工具”。它们虽然不是直接的 UI 控件,但却是构建一个成熟桌面应用不可或缺的核心基础设施。


一、 QPainter —— 自定义绘制引擎

导入:from PySide6.QtGui import QPainter, QPen, QBrush, QColor, QLinearGradient
通常,我们把 QPainter 和 paintEvent 结合使用,来绘制自定义形状、图片、复杂曲线、图表,或者实现动画效果。

1.1 基础绘制环境

1.2 坐标系统变换(终极核心,很多人忽略)

默认 (0,0) 坐标在控件左上角。你可以“移动”画布坐标系,做平移、旋转、缩放,从而画出复杂的旋转图形。

1.3 基础几何图形与文本绘制

1.4 高级工具:渐变填充与复杂路径

1.5 裁剪区域


二、 控件的生命周期事件重写(进阶视角)

导入:from PySide6.QtWidgets import QWidget
除了基础的 closeEvent 和 keyPressEvent,真正的界面交互依赖以下底层事件。


三、 QSettings —— 持久化配置(保存用户习惯与系统状态)

导入:from PySide6.QtCore import QSettings
QSettings 本质继承自 QObject,它是让软件记住用户每次打开界面的状态(如窗口大小、上次登录的账号)的终极利器。


四、 QTimer —— 定时器、超时与动画循环

导入:from PySide6.QtCore import QTimer
QTimer 继承自 QObject,是轮询、心跳、自动保存等场景的核心组件。

🟢 QTimer 的核心信号


五、 QClipboard —— 剪贴板操作与高级交互

导入:from PySide6.QtGui import QClipboard
剪贴板通过 QApplication.clipboard() 获取,用于系统级的文本、图片及 HTML 交互。

剪贴板监听信号


六、 QDrag —— 高级自定义拖拽与放置(非 UI 控件拖动)

导入:from PySide6.QtGui import QDrag
前面我们提过 setAcceptDrops 和 dropEvent(接收端),现在我们讲 发送端:如何把拖拽的东西从一个控件发出去。


七、 多线程 UI 更新与界面防卡死机制

导入:from PySide6.QtCore import QThread, Signal, QObject

7.1 QThread + 信号槽(标准安全跨线程通信)

绝对不要在工作线程内部直接调用 ui_label.setText("xx"),这会引发崩溃!必须用 信号/槽 机制。

class Worker(QThread):
    progress = Signal(int)
    def run(self):
        for i in range(101):
            self.progress.emit(i)
            self.msleep(50)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.worker = Worker()
        self.worker.progress.connect(self.update_ui) # 跨线程自动转为排队连接
        self.worker.start()
    
    def update_ui(self, val):
        self.ui.progressBar.setValue(val) # 安全!

7.2 极底层跨线程安全调用 QMetaObject.invokeMethod

在某些复杂场景下,如果你需要在非 UI 线程中直接强制在主线程执行一个函数,或者你需要让工作线程去操作不属于它的 UI,使用此“万金油”手法。

导入:from PySide6.QtCore import QMetaObject, Qt

7.3 QApplication.processEvents —— 强制处理事件防止界面冻结

如果你有一个非常耗时的循环(如 100 万次计算),可以直接用 for 循环。这时候为了保证 UI 界面不彻底卡死,可以在循环里定期抛出处理权。

def long_running_task(self):
    for i in range(1000000):
        # ... 繁重计算 ...
        if i % 1000 == 0:
            QApplication.processEvents() # 让 UI 喘口气,保持界面响应

八、 QGraphicsScene 与 QGraphicsView —— 2D 图形视图框架(高阶绘图)

导入:from PySide6.QtWidgets import QGraphicsScene, QGraphicsView, QGraphicsRectItem
为了绘制成百上千个可交互的复杂图形(像画图板、地图编辑器、流程图),用 QWidget 和 QPainter 会非常卡顿,而 QGraphicsView 和 QGraphicsScene 是 Qt 专门为此设计的终极利器。


九、 信号与槽高级用法扩充

导入:from PySide6.QtCore import QObject, Signal, Slot


十、 官方工具集成:Qt Designer + pyside6-uic

这是 PySide6 工业化开发的标配:界面用拖拽设计,逻辑用 Python 写。

10.1 快速命令行转换(最常用)

命令:pyside6-uic 你的界面.ui -o ui_你的界面.py
作用:将在 Qt Designer 中画好的 .ui 文件,直接转化为纯 Python 类代码文件。

10.2 经典加载方法(在 main.py 中集成)

不要直接修改 ui_你的界面.py!推荐采用“继承加载法”:

from PySide6.QtWidgets import QApplication, QMainWindow
from ui_你的界面 import Ui_MainWindow

class MyWindow(QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)  # 核心:调用 UI 类的方法初始化界面
        self.pushButton.clicked.connect(self.on_btn_click)

    def on_btn_click(self):
        print("业务逻辑触发")

10.3 QUiLoader 动态加载法(无需生成代码)

导入:from PySide6.QtUiTools import QUiLoader
如果你不想每次修改 UI 后重新运行 pyside6-uic,可以使用 QUiLoader 动态加载 .ui 文件。

loader = QUiLoader()
file = QFile("my_interface.ui")
file.open(QFile.ReadOnly)
window = loader.load(file)
file.close()

window.pushButton.clicked.connect(lambda: print("动态加载的按钮"))
window.show()

10.4 在 Designer 中“提升”自定义控件(Promoted Widgets)

你在 Designer 里拖了一个基础 QWidget,但你想在 Python 里把它变为你自己写的 MyCustomWidget,需要在 Designer 里进行“提升”。

  1. 右键点击该控件 -> Promote to...。
  2. 填写 Base class name(如 QWidget)和 Promoted class name(如 MyCustomWidget)。
  3. 保存 .ui。转换出的代码会自动把类型替换为 MyCustomWidget,你只需要在项目中定义好这个类即可。

附录:PySide6 官方内置可视化工具汇总

这些工具是通过 pip install PySide6 自动安装到你的 venv\Scripts 目录下的,直接打开终端输入命令即可。


十一、 高级补充遗漏细节(动画与性能计时)


PySide6-Advanced
一、 QPainter —— 自定义绘制引擎
四、 QTimer —— 定时器、超时与动画循环
五、 QClipboard —— 剪贴板操作与高级交互
七、 多线程 UI 更新与界面防卡死机制
十、 官方工具集成:Qt Designer + pyside6-uic
≡