PySide6从0开始学习的笔记(十一) QSS 属性选择器

在 PySide6 的 QSS 属性选择器中,所有控件的内置可访问属性 (即有 xxx() 方法可以读取的属性)都可作为筛选条件,不同控件有专属属性,也有跨控件通用属性。

下面将学习一些常用的部件和属性,完整官方文档见:https://doc.qt.io/qt-6/stylesheet-reference.html#list-of-sub-controls

一、常见的跨控件通用属性(所有控件都支持)

这类属性是 Qt 控件的基础属性,几乎所有控件(QWidget 子类)都具备,可作为通用筛选条件:

属性名 类型 说明 QSS 匹配示例
enabled 布尔 控件是否启用(可交互) QWidget[enabled=false](禁用控件)
visible 布尔 控件是否可见 QWidget[visible=true](可见控件)
focus 布尔 控件是否获取焦点 QLineEdit[focus=true](获焦输入框)
checked 布尔 控件是否选中(复选框 / 单选框 / 按钮等) QCheckBox[checked=true](选中复选框)
windowTitle 字符串 窗口标题(仅顶层窗口) QMainWindow[windowTitle=主界面]
objectName 字符串 控件唯一标识(setObjectName 设置) QPushButton[objectName=submitBtn]
minimumWidth 整数 控件最小宽度 QWidget[minimumWidth=200]
maximumHeight 整数 控件最大高度 QWidget[maximumHeight=100]
tooltip 字符串 控件提示文本(setToolTip 设置) QPushButton[tooltip=提交表单]

示例:通用属性筛选

复制代码
/* 禁用的所有控件置灰 */
QWidget[enabled=false] {
    color: #999;
    background-color: #f5f5f5;
}
/* 获取焦点的输入框高亮边框 */
QLineEdit[focus=true] {
    border: 2px solid #2196F3;
}
/* 提示文本包含"删除"的按钮标红 */
QPushButton[tooltip*=删除] {
    color: #f44336;
}

二、专属属性

以QPushButton为例:

QPushButton 作为高频控件,除了 flat,还有以下专属属性可用于 QSS 筛选:

属性名 类型 说明 QSS 匹配示例
text 字符串 按钮显示的文字 QPushButton[text=删除](文字为 "删除")
default 布尔 是否为 "默认按钮"(回车触发) QPushButton[default=true](默认提交按钮)
autoDefault 布尔 是否自动成为默认按钮 QPushButton[autoDefault=false]
checkable 布尔 按钮是否可选中(切换状态) QPushButton[checkable=true](可选中按钮)
checked 布尔 可选中按钮的选中状态(继承通用属性) QPushButton[checkable=true][checked=true]
iconSize QSize 图标尺寸(需匹配宽高,仅支持数值) QPushButton[iconSize=64,64](图标 64x64)
shortcut 字符串 快捷键(如 Ctrl+S QPushButton[shortcut=Ctrl+S]

示例:QPushButton 专属属性筛选

复制代码
/* 默认按钮(回车触发)强化样式 */
QPushButton[default=true] {
    background-color: #2196F3;
    color: white;
    border-radius: 4px;
    padding: 10px 20px;
}
/* 可选中的按钮(切换按钮) */
QPushButton[checkable=true] {
    background-color: #4CAF50;
    color: white;
}
/* 文字为"取消"的按钮灰色样式 */
QPushButton[text=取消] {
    background-color: #9E9E9E;
    color: white;
}
  • 注意:
  1. Qt 样式表(QSS)的属性选择器严格遵循「属性存在 + 属性值匹配 」的逻辑,所以要注意属性调用的前提,比如checked属性有特殊前提的:

checked是「可勾选控件(checkable=true)」的专属状态属性,只有当控件的checkabletrue时,checked属性才会被 Qt 识别

所以,下面的代码是不生效的:

python 复制代码
import sys

from PySide6.QtWidgets import QApplication, QPushButton, QVBoxLayout
from PySide6.QtWidgets import QWidget


app = QApplication(sys.argv)
window = QWidget()
btn1 = QPushButton("确定")
btn1.setCheckable(True)
btn1.clicked.connect(lambda: btn1.setStyleSheet(btn1.styleSheet()))

layout = QVBoxLayout(window)
layout.addWidget(btn1)
window.setStyleSheet("""    
    QPushButton[checkable=true] {
        background-color: #ff0000;
        color: white;
        padding: 10px;
        border: none;
        border-radius: 5px;
    }
    QPushButton[checked=true] {
        background-color: #00ff00;
    }
}""")
window.resize(300, 200)
window.show()
sys.exit(app.exec())

因为默认QPushButton的checkable=False,那么它就不具备checked这个属性,也就无从判断[checked=true]这个条件。正确写法是

python 复制代码
QPushButton[checkable=true][checked=true] {
        background-color: #00ff00;

在[checkable=true]的QPushButton范围内判断[checked=true]。

  1. 当判断条件的属性发生了变化,就要重新加载一次样式表以更新样式。例如:
python 复制代码
import sys

from PySide6.QtWidgets import QApplication, QPushButton, QVBoxLayout
from PySide6.QtWidgets import QWidget


app = QApplication(sys.argv)
window = QWidget()
btn1 = QPushButton("确定")
btn1.setCheckable(True)
# btn1.clicked.connect(lambda :btn1.setStyleSheet(btn1.styleSheet()))
btn2 = QPushButton("确定")
btn3 = QPushButton("取消")
layout = QVBoxLayout(window)
layout.addWidget(btn1)
layout.addWidget(btn2)
layout.addWidget(btn3)
window.setStyleSheet("""    
    QPushButton[checkable=true] {
        background-color: #ff0000;
        color: white;
        padding: 10px;
        border: none;
        border-radius: 5px;
    }
    QPushButton[checkable=true][checked=true] {
        background-color: #00ff00;
    }
}""")
window.resize(300, 200)
window.show()
sys.exit(app.exec())

运行后发现,即使btn1的checked属性已经发生了变化,它的背景色仍然没有变化。这是因为虽然btn1的checked属性发生了变化,但是它在上一次设置样式表时并不符合"[checked=true]"这个条件,所以就要在checked属性发生了变化之后再次给它设置样式表,这一次它符合"[checked=true]"这个条件:

增加语句:

python 复制代码
btn1.clicked.connect(lambda :btn1.setStyleSheet(btn1.styleSheet()))

重新设置一次样式表。

比运行一次"btn1.setStyleSheet(btn1.styleSheet()"更好的办法是使用btn.style().unpolish(btn) + btn.style().polish(btn)来清除样式缓存和重新初始化:

python 复制代码
btn.style().unpolish(btn)
btn.style().polish(btn)
  • unpolish(btn) :清除控件 btn 关联的样式缓存(如样式表解析结果、原生样式的状态缓存),解除样式与控件的绑定;
  • polish(btn):重新让样式系统「处理」控件,重新解析样式规则(包括样式表、原生样式、自定义样式),并应用到控件上。

完整代码:

python 复制代码
import sys

from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton

app = QApplication(sys.argv)
window = QWidget()
window.resize(300, 100)
layout = QVBoxLayout(window)
btn = QPushButton("按钮")
btn.setCheckable(True)

def btn_clicked():
    btn.style().unpolish(btn)
    btn.style().polish(btn)

btn.clicked.connect(btn_clicked)

layout.addWidget(btn)
window.setStyleSheet("""
    QPushButton[checked=true] {
    background-color: red;}
    """)

window.show()
sys.exit(app.exec())

当然了,最好的办法是用伪状态来取代属性,这是最优解:

python 复制代码
QPushButton[checkable=true]:checked {}

全部代码:

python 复制代码
import sys

from PySide6.QtWidgets import QApplication, QPushButton, QVBoxLayout
from PySide6.QtWidgets import QWidget


app = QApplication(sys.argv)
window = QWidget()
btn1 = QPushButton("确定")
btn1.setCheckable(True)

layout = QVBoxLayout(window)
layout.addWidget(btn1)
window.setStyleSheet("""    
    QPushButton[checkable=true] {
        background-color: #ff0000;
        color: white;
        padding: 10px;
        border: none;
        border-radius: 5px;
    }
    QPushButton[checkable=true]:checked {
        background-color: #00ff00;
        color: black;
    }
}""")
window.resize(300, 200)
window.show()
sys.exit(app.exec())

还有,基于上面讲过的原因,不要把

python 复制代码
QPushButton[checkable=true]:checked { /*[checkable=true]必不可少*/

写成

python 复制代码
QPushButton:checked {

因为默认的QPushButton是没有checked这个伪状态的。

三、常用控件核心属性(按控件类型分类)

不同控件有专属核心属性,是 QSS 精细化样式的关键,以下整理高频控件的可筛选属性:

1. QLineEdit(输入框)
属性名 类型 说明 QSS 匹配示例
readOnly 布尔 是否只读 QLineEdit[readOnly=true]
placeholderText 字符串 占位提示文本 QLineEdit[placeholderText*=手机号]
echoMode 枚举 输入回显模式(如密码隐藏) QLineEdit[echoMode="Password"]

示例:输入框属性筛选

python 复制代码
import sys

from PySide6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QLineEdit
from PySide6.QtWidgets import QWidget


app = QApplication(sys.argv)
window = QWidget()
line_edit1 = QLineEdit()
line_edit1.setReadOnly(True)
line_edit2 = QLineEdit()
line_edit2.setEchoMode(QLineEdit.Password)

layout = QVBoxLayout(window)
layout.addWidget(line_edit1)
layout.addWidget(line_edit2)
window.setStyleSheet("""    
    /* 只读输入框禁用编辑样式 */
    QLineEdit[readOnly=true] {
        background-color: #f5f5f5;
        border: 1px solid red;
        color: #666;
}
    /* 密码输入框自定义样式 */
    QLineEdit[echoMode="Password"] {
        border: 2px solid green;
}
    }
}""")
window.resize(300, 200)
window.show()
sys.exit(app.exec())
2. QCheckBox/QRadioButton(复选框 / 单选框)
属性名 类型 说明 QSS 匹配示例
checked 布尔 是否选中(核心) QRadioButton[checked=true]
tristate 布尔 是否支持半选状态(仅复选框) QCheckBox[tristate=true]
indeterminate 布尔 是否半选状态(仅复选框) QCheckBox[indeterminate=true]
text 字符串 提示文字 QCheckBox[text*=同意]

示例:复选框状态样式

python 复制代码
import sys

from PySide6.QtCore import Qt
from PySide6.QtWidgets import QApplication, QPushButton, QVBoxLayout, QLineEdit, QCheckBox
from PySide6.QtWidgets import QWidget


app = QApplication(sys.argv)
window = QWidget()

check_box = QCheckBox("三态复选框")
check_box.setTristate(True)  # 开启三态模式
check_box.setCheckState(Qt.PartiallyChecked)

layout = QVBoxLayout()
layout.addWidget(check_box)
window.setLayout(layout)


window.setStyleSheet("""    
    /*基础复选框样式(控制文字与框体间距) */
    QCheckBox {
        font-size: 20px;
        spacing: 10px;  /* 框体和文字的间距,避免重叠 */
    }
    /*设置复选框的指示器尺寸*/
    QCheckBox::indicator {
        width: 24px;    /* 宽度 */
        height: 24px;   /* 高度 */
}
    /* 半选状态的复选框 */
    QCheckBox[tristate=true]::indicator:indeterminate {
     background-color: red;
}
    /* 选中状态的复选框 */
   QCheckBox[tristate=true]::indicator:checked {
     background-color: green;
}
    /* 未选中状态的复选框 */
    QCheckBox[tristate=true]::indicator:unchecked {
     background-color: blue;
}
    """)
window.resize(300, 200)
window.show()
sys.exit(app.exec())
3. QComboBox(下拉框)
属性名 类型 说明 QSS 匹配示例
editable 布尔 是否可编辑(输入文本) QComboBox[editable=true]
currentIndex 整数 当前选中项索引 QComboBox[currentIndex=0](默认第一项)
count 整数 下拉选项数量 QComboBox[count>5](选项 > 5 个)

QComboBox的子部件

| 子部件名 | 说明 | 备注 |
| lineEdit | 文本编辑框 | 当setEditable(True),才有此编辑框。可通过 combobox.lineEdit().setStyleSheet("")设置 |
| drop_down | 下拉按钮 | QComboBox::drop-down { } |

down-arrow 下拉按钮上的箭头图片 QComboBox::down-arrow { }

示例:可编辑下拉框样式

python 复制代码
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QComboBox, QLineEdit
import sys

app = QApplication(sys.argv)
window = QWidget()
window.resize(300, 100)
layout = QVBoxLayout(window)
cb = QComboBox()
cb.addItems(["1", "2", "3"])
cb.setEditable(True)

cb.setStyleSheet("""QComboBox {
    border: 1px solid gray;
    border-radius: 3px;
    padding: 1px 18px 1px 3px;
    font-size: 30px;
    min-width: 6em;
}
QComboBox::drop-down {    
    width: 30px;
    background: white;
    
}
QComboBox[editable=true] {
    background: blue;
}

QComboBox::down-arrow {
    image: url(arrow_down1.png);
}""")

# cb.lineEdit().setStyleSheet("background-color:red;")
layout.addWidget(cb)
window.show()
sys.exit(app.exec())

QComboBox的linEdit子部件(文本编辑框))很奇怪,并不能通过"QComboBox::子部件"的方式来修改,只能用类似

python 复制代码
cb.lineEdit().setStyleSheet("background-color:red;")

或:

python 复制代码
from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QComboBox, QLineEdit
import sys

app = QApplication(sys.argv)
window = QWidget()
window.resize(300, 100)
layout = QVBoxLayout(window)
cb = QComboBox()
cb.addItems(["1", "2", "3"])
cb.setEditable(True)
line_edit = QLineEdit()
line_edit.setStyleSheet("""
    QLineEdit {
        background-color:red;
    }""")
cb.setLineEdit(line_edit)

layout.addWidget(cb)


window.show()
sys.exit(app.exec())

这样的方法来间接设定。我查找了各种官方文档也没能找到在样式表中修改它的方法。看上去好像QComboBox的QLinEdit部件并不是它的子部件,QComboBox像是一个用QLinEdit、下拉按钮、下拉箭头拼凑起来的缝合怪。

4. QSlider(滑块)
属性名 类型 说明 QSS 匹配示例
orientation 枚举 方向(0 = 水平,1 = 垂直) QSlider[orientation=1](垂直滑块)
minimum 整数 最小值 QSlider[minimum=0]
maximum 整数 最大值 QSlider[maximum=100]
value 整数 当前值 QSlider[value>50]

前面已经有滑块的学习记录https://blog.csdn.net/xulibo5828/article/details/156028492

5. QProgressBar(进度条)
属性名 类型 说明 QSS 匹配示例
value 整数 当前进度值 QProgressBar[value>=100](进度完成)
minimum/maximum 整数 最小 / 最大值 QProgressBar[maximum=100]
textVisible 布尔 是否显示进度文字 QProgressBar[textVisible=false]

下一节详细学习进度条。

四、自定义属性(扩展无内置属性的场景)

如果内置属性无法满足筛选需求,可通过 setProperty() 给控件设置自定义属性,QSS 同样支持匹配:

步骤 1:设置自定义属性
python 复制代码
btn = QPushButton("危险按钮")
# 设置自定义属性:type=danger
btn.setProperty("type", "danger")

# 如果是动态修改属性,需刷新样式才能生效
btn.style().unpolish(btn)
btn.style().polish(btn)
步骤 2:QSS 匹配自定义属性
python 复制代码
import sys

from PySide6.QtWidgets import QApplication, QWidget, QVBoxLayout, QPushButton

app = QApplication(sys.argv)
window = QWidget()
window.resize(300, 100)
layout = QVBoxLayout(window)

btn = QPushButton("危险按钮")
# 设置自定义属性:type=danger、size=large
btn.setProperty("type", "danger")

btn2 = QPushButton("启动按钮")
btn2.setProperty("func", "start")

layout.addWidget(btn)
layout.addWidget(btn2)
window.setStyleSheet("""
    QPushButton[type=danger] {
    background-color: red;}
    QPushButton[func=start] {
    background-color: green;}
    """)

window.show()
sys.exit(app.exec())

五、关键注意事项

  1. 属性值类型匹配

    • 布尔值:必须写 true/false(小写),不能写 True/False1/0
    • 字符串:无需加引号(如 [text=删除],而非 [text="删除"]);
    • 复合类型(如 QSize):用逗号分隔(如 [iconSize=64,64])。
  1. 动态属性刷新 运行时修改控件属性(如 btn.setFlat(True)btn.setProperty("type", "success"))后,需手动刷新样式:

    复制代码
    widget.style().unpolish(widget)  # 清除旧样式缓存
    widget.style().polish(widget)    # 应用新属性的样式
    widget.update()                  # 刷新控件显示
  2. 优先级规则 属性选择器优先级:控件类[属性1=值1][属性2=值2](多属性组合) > 控件类[属性=值] > 纯类选择器(如 QPushButton)。

总结

QSS 属性选择器的核心是「控件的可访问属性」,可筛选的属性分为三类:

  1. 通用属性(所有控件):enabled/focus/objectName 等;
  2. 控件专属属性(如 QPushButton 的 default/checkable、QLineEdit 的 readOnly);
  3. 自定义属性(通过 setProperty 扩展)。

灵活组合这些属性,可实现 "精准定位控件 + 差异化样式",避免为每个控件单独写样式,大幅提升 QSS 的复用性和维护性。

相关推荐
AAA_bo12 小时前
liunx安装canda、python、nodejs、git,随后部署私有网页内容提取工具--JinaReader全攻略
linux·python·ubuntu·typescript·aigc·python3.11·jina
中屹指纹浏览器2 小时前
2025技术解析:分布式指纹协同管理技术底层实现与规模化运营逻辑
经验分享·笔记
风123456789~2 小时前
【健康管理】第8章 身体活动基本知识 2/2
笔记·考证·健康管理
代码游侠2 小时前
学习笔记——Linux进程间通信(IPC)
linux·运维·笔记·学习·算法
高洁012 小时前
DNN案例一步步构建深层神经网络(3)
python·深度学习·算法·机器学习·transformer
AI_56782 小时前
Jupyter交互式数据分析的效率革命
开发语言·python
superman超哥2 小时前
仓颉语言中并发集合的实现深度剖析与高性能实践
开发语言·后端·python·c#·仓颉
superman超哥2 小时前
仓颉语言中原子操作的封装深度剖析与无锁编程实践
c语言·开发语言·后端·python·仓颉
拾贰_C2 小时前
【Anaconda | Python | pytorch】sklearn scikit-learn 报错:
pytorch·python·sklearn