我在QT中设置QSlider使用的是qss样式,我一开始就设置了
QSlider::groove: horizontal {
background: rgb(217,221,227);
height: 14px;
border-radius: 7px;
}
QSlider::handle: horizontal {
background: #0078D7;
border: 2px solid white;
width: 10px;
height: 10px;
border-radius: 7px;
}
这一切都很好,但我想为滑动过程添加颜色,所以我添加了它
QSlider::sub-page:horizontal {
background: rgb(56, 121, 216);
height: 8px;
border-radius: 7px;
}
QSlider::add-page:horizontal {
background: rgb(217,221,227);
height: 8px;
border-radius: 7px;
}
但这会导致圆角边框在开始和结束位置消失,这种情况下如何正确显示圆角边框?
我不是 100% 确定,但恐怕仅使用 QSS 无法立即实现这一点。
问题来自两个方面:
add-page
和sub-page
矩形是根据凹槽矩形和手柄中心创建的(例如,对于sub-page
,它是“夹”到手柄中间的凹槽矩形);这就是 QSS 实现绘制 QSlider 的
add-page
和 sub-page
子控件的方式(请参阅 源代码中的
PseudoElement_SliderSubPage
用法),并且无法覆盖该行为。
唯一可能的解决方案是使用精心设计的 QSlider 子类,根据值和句柄位置并考虑其大小来更新其样式表。
例如,如果它接近最小值并且半径小于滑块高度的一半,则我们通过强制其为
::groove
的颜色来覆盖 sub-page
背景,同时将 sub-page
背景设置为透明。
OP 没有指定语言,而且我无法真正编写正确的 C++ 代码,因此我将提供一个基于 Python 的示例,该示例也应该作为伪代码工作。
class RoundedSlider(QSlider):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._updateQSS()
def _updateQSS(self):
halfHeight = self.height() // 2
grooveWidth = self.width() - halfHeight * 2
p = self.style().sliderPositionFromValue(
self.minimum(), self.maximum(),
self.value(), grooveWidth
)
if p < halfHeight:
qss = '''
QSlider::groove {
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop: 0.0 rgb(56, 121, 216),
stop: 0.5 rgb(56, 121, 216),
stop: 0.5 transparent
);
}
QSlider::sub-page {
background: transparent;
}
QSlider::add-page {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
'''
elif p > grooveWidth - halfHeight:
qss = '''
QSlider::groove {
background: qlineargradient(x1:0, y1:0, x2:1, y2:0,
stop: 0.5 transparent,
stop: 0.5 rgb(217, 221, 227),
stop: 1.0 rgb(217, 221, 227)
);
}
QSlider::add-page {
background: transparent;
}
QaSlider::sub-page {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
'''
else:
qss = ''
self.setStyleSheet(qss)
def sliderChange(self, change):
if change == self.SliderValueChange:
self.ensurePolished()
self._updateQSS()
super().sliderChange(change)
def resizeEvent(self, event):
super().resizeEvent(event)
self._updateQSS()
app = QApplication([])
app.setStyleSheet('''
QSlider::groove:horizontal {
background: rgb(217, 221, 227);
height: 14px;
border-radius: 7px;
}
QSlider::handle:horizontal {
background: #0078D7;
border: 2px solid white;
width: 10px;
height: 10px;
border-radius: 7px;
}
QSlider::sub-page:horizontal {
background: rgb(56, 121, 216);
border-radius: 7px;
}
QSlider::add-page:horizontal {
background: rgb(217, 221, 227);
border-radius: 7px;
}
''')
test = QWidget()
layout = QVBoxLayout(test)
for i in range(4):
layout.addWidget(RoundedSlider(Qt.Horizontal, maximum=50, value=i * 2))
test.show()
app.exec()
请注意,上述实现仅适用于水平滑块而不是反向滑块。如果您需要使用垂直滑块或反转值,则必须进行相应的修复。
另请注意,使用线性渐变是为了避免圆形边框处的抗锯齿造成的小伪像。
最后,请注意,您最初的 QSS 有一个重要的语法错误,因为您在
QSlider::groove: horizontal
和 QSlider::handle: horizontal
中添加了一个空格。我没有检查最新的 Qt 版本是否能够解决这个问题,但它仍然是一个无效的语法,在任何情况下都应该避免。