为小部件应用程序设置样式

Qt Widgets 应用程序根据平台使用默认主题。 在某些情况下,存在系统范围的配置会修改 Qt 主题, 导致应用程序显示不同。

然而,你可以自己处理你的小部件,并为每个组件提供自定义样式。例如,看看以下简单的代码片段:

import sys
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QLabel

if __name__ == "__main__":
    app = QApplication()
    w = QLabel("This is a placeholder text")
    w.setAlignment(Qt.AlignCenter)
    w.show()
    sys.exit(app.exec())

当你执行这段代码时,你会看到一个简单的QLabel居中显示,并带有占位符文本。

Simple Widget with no style

您可以使用类似CSS的语法来设计您的应用程序。 有关更多信息,请参阅Qt样式表参考

一个QLabel可以通过设置一些CSS属性来改变样式,例如background-colorfont-family,让我们看看这些更改后的代码是什么样的:

import sys
from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QLabel

if __name__ == "__main__":
    app = QApplication()
    w = QLabel("This is a placeholder text")
    w.setAlignment(Qt.AlignCenter)
    w.setStyleSheet("""
        background-color: #262626;
        color: #FFFFFF;
        font-family: Titillium;
        font-size: 18px;
        """)
    w.show()
    sys.exit(app.exec())

现在当你运行代码时,注意QLabel看起来与你的自定义样式不同:

Simple Widget with Style

注意

如果您没有安装Titillium字体,您可以尝试使用您喜欢的任何其他字体。 请记住,您可以使用QFontDatabase列出已安装的字体, 特别是families()方法。

像你在前面的代码片段中那样分别对每个UI元素进行样式设置是一项繁重的工作。更简单的替代方法是使用Qt样式表,这是一个或多个.qss文件,用于定义应用程序中UI元素的样式。

更多示例可以在Qt样式表示例文档页面中找到。

Qt 样式表

警告

在开始修改您的应用程序之前,请记住您将负责应用程序的所有图形细节。 更改边距和大小可能会导致看起来奇怪或不正确,因此在更改样式时需要小心。 建议创建一个全新的Qt样式以覆盖所有可能的极端情况。

一个 qss 文件与 CSS 文件非常相似,但你需要指定 Widget 组件,并可选地指定对象的名称:

QLabel {
    background-color: red;
}

QLabel#title {
    font-size: 20px;
}

第一种样式为应用程序中的所有QLabel对象定义了background-color,而后一种样式仅对title对象进行样式设置。

注意

你可以使用setObjectName(str)函数为任何Qt对象设置对象名称,例如:对于一个label = QLabel(“Test”),你可以写label.setObjectName(“title”)

一旦你为你的应用程序有了一个qss文件,你可以通过读取文件并使用QApplication.setStyleSheet(str)函数来应用它:

if __name__ == "__main__":
    app = QApplication()

    w = Widget()
    w.show()

    with open("style.qss", "r") as f:
        _style = f.read()
        app.setStyleSheet(_style)

    sys.exit(app.exec())

拥有一个通用的qss文件可以让你将代码的样式方面解耦,而不将其混入通用功能的中间,你可以简单地启用或禁用它。

看看这个新例子,有更多的小部件组件:

 1
 2class Widget(QWidget):
 3    def __init__(self, parent=None):
 4        super(Widget, self).__init__(parent)
 5
 6        menu_widget = QListWidget()
 7        for i in range(10):
 8            item = QListWidgetItem(f"Item {i}")
 9            item.setTextAlignment(Qt.AlignCenter)
10            menu_widget.addItem(item)
11
12        text_widget = QLabel(_placeholder)
13        button = QPushButton("Something")
14
15        content_layout = QVBoxLayout()
16        content_layout.addWidget(text_widget)
17        content_layout.addWidget(button)
18        main_widget = QWidget()
19        main_widget.setLayout(content_layout)
20
21        layout = QHBoxLayout()
22        layout.addWidget(menu_widget, 1)
23        layout.addWidget(main_widget, 4)

这将显示一个两列的小部件,左侧有一个QListWidget,右侧有一个QLabel和一个QPushButton。当你运行代码时,它看起来像这样:

Widget with no style

如果您向之前描述的style.qss文件中添加内容,您可以修改之前示例的外观和感觉:

 1QListWidget {
 2    color: #FFFFFF;
 3    background-color: #33373B;
 4}
 5
 6QListWidget::item {
 7    height: 50px;
 8}
 9
10QListWidget::item:selected {
11    background-color: #2ABf9E;
12}
13
14QLabel {
15    background-color: #FFFFFF;
16    qproperty-alignment: AlignCenter;
17}
18
19QPushButton {
20    background-color: #2ABf9E;
21    padding: 20px;
22    font-size: 18px;
23}

样式主要改变了不同小部件的颜色,调整了对齐方式,并包含了一些间距。 你也可以在QListWidget的项目上使用基于状态的样式,例如,根据它们是否被选中来对它们进行不同的样式设置。

在应用了本主题中探讨的所有样式替代方案后,请注意QLabel示例现在看起来大不相同。尝试运行代码以检查其新外观:

Widget with style

您可以自由调整样式表,为所有应用程序提供非常美观的外观和感觉。