QT QSlider样式表导致圆角边框消失

问题描述 投票:0回答:1

我在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;
}

但这会导致圆角边框在开始和结束位置消失,这种情况下如何正确显示圆角边框?

qt qwidget qtstylesheets qslider
1个回答
0
投票

我不是 100% 确定,但恐怕仅使用 QSS 无法立即实现这一点。

问题来自两个方面:

  • add-page
    sub-page
    矩形是根据凹槽矩形和手柄中心创建的(例如,对于
    sub-page
    ,它是“夹”到手柄中间的凹槽矩形);
  • QSS 会使任何小于其所基于的尺寸一半的边框半径无效,从而导致绘制一个普通矩形;

这就是 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 版本是否能够解决这个问题,但它仍然是一个无效的语法,在任何情况下都应该避免。

© www.soinside.com 2019 - 2024. All rights reserved.