PySide6-Advanced


前言:本文件涵盖范围

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


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

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

1.1 基础绘制环境

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

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

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

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

1.5 裁剪区域


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

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


三、 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
前面我们提过 setAcceptDropsdropEvent(接收端),现在我们讲 发送端:如何把拖拽的东西从一个控件发出去。


七、 多线程 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
为了绘制成百上千个可交互的复杂图形(像画图板、地图编辑器、流程图),用 QWidgetQPainter 会非常卡顿,而 QGraphicsViewQGraphicsScene 是 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