7. PySide6 样式和动画

QSS 基本语法

类似 CSS,QSS 每一条都是由一个选择器和一组声明构成:

  • 选择器选出要对哪种控件进行样式修改
  • 每个声明都是键值对,键为属性,值为属性值
QWidget {
    color: #000;
    background-color: #fff;
}

使用方式

为降低耦合,往往把 QSS 写在一个单独的 style.qss 文件中,然后在 main.pyQMainWindow 中加载样式。

新建一个扩展名为 .qss 的文件,如 style.qss,编辑内容。

QWidget {
    color: #e34fff;
    background-color: #000;
}

main.py 中加载样式:

import sys

from PySide6.QtCore import QFile, Qt
from PySide6.QtWidgets import QApplication, QLabel, QMainWindow


class QSSLoader:
    def __init__(self, path: str) -> None:
        self._path = path

    def load(self) -> str:
        f = QFile(self._path)
        f.open(QFile.ReadOnly | QFile.Text)
        stylesheet = f.readAll()
        return stylesheet.data().decode("utf-8")


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("QSS Demo")
        self.resize(400, 300)

        label = QLabel("Hello World")
        label.setAlignment(Qt.AlignCenter)
        self.setCentralWidget(label)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.setStyleSheet(QSSLoader("style.qss").load())
    window.show()
    sys.exit(app.exec())

动态修改

部分参考了 hektorprofe/curso-qt-pyside-udemy在新窗口打开 的代码。

import sys

from PySide6.QtWidgets import (
    QApplication,
    QCheckBox,
    QFormLayout,
    QLabel,
    QLineEdit,
    QMainWindow,
    QPlainTextEdit,
    QPushButton,
    QRadioButton,
    QSpinBox,
    QVBoxLayout,
    QWidget,
)

STYLE = """QMainWindow {
    background-color: #212121;
}
QLabel {
    color: #e9e9e9;
}
QPushButton {
    background-color: orange;
    font-family: 'Arial';
    font-size: 14px;
    font-weight: bold;
}
"""


class QSSEditor(QWidget):
    def __init__(self, parent: QWidget | None = None):
        super().__init__()

        self._parent = parent
        self.resize(480, 320)
        self.setWindowTitle("QSS Editor")

        self._editor = QPlainTextEdit()
        self._editor.setStyleSheet(
            "background-color: #212121;color: #e9e9e9;"
            "font-family: Consolas; font-size: 16px; "
        )
        self._editor.setFont("Consolas")
        self._editor.setPlainText(STYLE)
        self._editor.textChanged.connect(self.update_style)

        layout = QVBoxLayout()
        layout.addWidget(self._editor)
        self.setLayout(layout)

        self.show()

    def update_style(self):
        qss = self._editor.toPlainText()
        try:
            self._parent.setStyleSheet(qss)
        except:
            pass


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        layout = QFormLayout()
        layout.addRow("QCheckBox", QCheckBox())
        layout.addRow("QRadioButton", QRadioButton())
        layout.addRow("QLabel", QLabel("QLabel"))
        layout.addRow("QPushButton", QPushButton("QPushButton"))
        layout.addRow("QLineEdit", QLineEdit("QLineEdit"))
        layout.addRow("QSpinBox", QSpinBox())

        widget = QWidget()
        widget.setLayout(layout)
        self.setCentralWidget(widget)

        label = QLabel("QLabel")
        label.setObjectName("label")
        layout.addRow(label)

        self._qss_editor = QSSEditor(self)
        self.setStyleSheet(STYLE)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec())