1、通过伪状态来改变外观
伪状态是一种特殊的状态,通常用于描述控件在特定条件下的外观变化。这些状态不是控件的实际属性,而是用于在样式表中应用不同样式的标记。
以QPushButton为例。在 PySide6 中,QPushButton 具有多种伪状态,每种伪状态可以通过样式表(QSS)来设定样式。以下是一些常见的伪状态及其对应的样式表设置方法:
正常状态(Normal):按钮处于未被点击、未被禁用的状态。
QPushButton {
background-color: lightblue;
color: black;
}
悬停状态(Hover):当鼠标悬停在按钮上时。
QPushButton:hover {
background-color: lightgreen;
color: black;
}
按下状态(Pressed):按钮被点击时。
QPushButton:pressed {
background-color: red;
color: white;
}
禁用状态(Disabled):按钮被禁用时。
获得焦点状态(Focus):按钮获得键盘焦点时。
活动状态(Active):按钮被激活时(通常用于不同的窗体或选项卡)。
checked:控件(单选按钮)被选中时。
demo:
from PySide6.QtWidgets import QApplication, QPushButton, QWidget, QVBoxLayout
app = QApplication([])
window = QWidget()
layout = QVBoxLayout()
button = QPushButton("Click Me")
button.setStyleSheet("""
QPushButton {
background-color: lightblue;
color: black;
}
QPushButton:hover {
background-color: lightgreen;
color: black;
}
QPushButton:pressed {
background-color: red;
color: white;
}
QPushButton:disabled {
background-color: gray;
color: lightgray;
}
""")
layout.addWidget(button)
window.setLayout(layout)
window.show()
app.exec()
运行截图:
2、通过自定义特性来改变外观
除了使用默认的伪特性,还可以自定义特性,通过改变自定义特性的方法改变外观。
from PySide6.QtWidgets import QApplication, QPushButton, QWidget, QVBoxLayout
app = QApplication([])
class Window(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUI()
self.show()
def setupUI(self):
layout = QVBoxLayout()
self.button_1 = QPushButton("Button_1")
self.button_2 = QPushButton("Button_2")
# 自定义的特性custom_attribute
self.button_2.setProperty("custom_attribute", False)
self.button_2.setStyleSheet("""
QPushButton[custom_attribute="true"] {
background-color: lightblue;
color: red;
}
""")
layout.addWidget(self.button_1)
layout.addWidget(self.button_2)
self.setLayout(layout)
self.slot_signal()
# 槽函数和信号连接
def slot_signal(self):
# 按钮1点击的槽函数
def bt1_clicked():
this = self.button_2
this.setProperty("custom_attribute", not this.property("custom_attribute"))
this.setStyleSheet(this.styleSheet())
# 按钮1点击的连接
self.button_1.clicked.connect(bt1_clicked)
window = Window()
app.exec()
示例代码中, 将按钮2设置了一个自定义特性custom_attribute,并且将其初始化为False:
self.button_2.setProperty("custom_attribute", False)
然后将按钮2的外观与自定义特性关联:
self.button_2.setStyleSheet("""
QPushButton[custom_attribute="true"] {
background-color: lightblue;
color: red;
}
再将按钮2的自定义特性的改变与按钮1的点击连接:
# 按钮1点击的连接
self.button_1.clicked.connect(bt1_clicked)
def bt1_clicked():
this = self.button_2
this.setProperty("custom_attribute", not this.property("custom_attribute"))
this.setStyleSheet(this.styleSheet())
这样,每点击一次按钮1,按钮2的自定义特性就反转,并根据样式表改变外观。
需要注意的是,由于并没有给自定义特性的改变指定触发的事件,所以当自定义特性改变时,按钮并不能自动根据样式表改变外观,即使用update()和repaint()重绘都不行,在一些博主的demo中,使用update()和repaint()来改变外观,经过测试,并不能实现外观的改变,这个误导,耽误了我非常多的时间和精力。查阅了很多技术文档之后,正确的方法应该是*.setStyleSheet(*.styleSheet()),这样可以重新设置和应用样式表。另外,根据技术文档,在一些极端情况下,*.setStyleSheet(*.styleSheet())也有可能无效,可以采用下面这个语句组合来实现强制的样式表重新应用:
btn.style().unpolish(btn)
btn.style().polish(btn)
btn.update()
使用polish方法的完整代码:
from PySide6.QtWidgets import QApplication, QPushButton, QWidget, QVBoxLayout
app = QApplication([])
class Window(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUI()
self.show()
def setupUI(self):
layout = QVBoxLayout()
self.button_1 = QPushButton("Button_1")
self.button_2 = QPushButton("Button_2")
# 自定义的特性custom_attribute
self.button_2.setProperty("custom_attribute", False)
self.button_2.setStyleSheet("""
QPushButton[custom_attribute="true"] {
background-color: lightblue;
color: red;
}
""")
layout.addWidget(self.button_1)
layout.addWidget(self.button_2)
self.setLayout(layout)
self.slot_signal()
# 槽函数和信号连接
def slot_signal(self):
# 按钮1点击的槽函数
def bt1_clicked():
this = self.button_2
this.setProperty("custom_attribute", not this.property("custom_attribute"))
this.style().unpolish(this)
this.style().polish(this)
this.update()
# 按钮1点击的连接
self.button_1.clicked.connect(bt1_clicked)
window = Window()
app.exec()
polish的更详细解释:PySide的style().unpolish()与style().unpolish()-CSDN博客