【问题标题】:Customizing the QScrollbar in PyQt在 PyQt 中自定义 QScrollbar
【发布时间】:2016-07-26 08:18:59
【问题描述】:

通常来自 PyQt 的默认 QScrollBar 对于高 dpi 显示来说太小了。这就是为什么有必要调整它们。无论如何,一旦你这样做了,为什么不从你可以做出的美学改进中受益呢?

这是您可以调整 QScrollBar 的“外观”的方法:

########################################
#     My custom QScrollArea            #
#     widget                           #
########################################

class MyScrollArea(QScrollArea):

    def __init__(self, parent):
        super(MyScrollArea, self).__init__(parent)
        ...

        self.setStyleSheet("""QScrollBar:vertical {
                    width: 45px;
                    margin: 45px 0 45px 0;
                    background: #32CC99;
                  }

                  QScrollBar::handle:vertical {
                    border: 10px solid grey;
                    background: white;
                    min-height: 10px;
                  }

                  QScrollBar::add-line:vertical {
                    border: 2px solid grey;
                    background: none;
                    height: 45px;
                    subcontrol-position: bottom;
                    subcontrol-origin: margin;
                  }

                  QScrollBar::sub-line:vertical {
                    border: 2px solid grey;
                    background: none;
                    height: 45px;
                    subcontrol-position: top;
                    subcontrol-origin: margin;
                  }

                  QScrollBar::up-arrow:vertical {
                    border: 5px solid grey;
                    height: 40px; 
                    width: 40px 
                  }

                  QScrollBar::down-arrow:vertical {
                    border: 5px solid grey;
                    height: 40px; 
                    width: 40px                              
                  }""")
        ...

    ### End init ###

### End Class ###

我找到了以下关于如何设置样式表的文档:

http://doc.qt.io/qt-4.8/stylesheet-examples.html#customizing-qscrollbar d

问题:

自定义 QScrollBars 后,它们可以完美运行。但是当点击手柄或箭头时,用户不会得到任何视觉反馈。例如点击箭头,不会产生箭头被按下的视觉反馈。

下面是一个例子:

【问题讨论】:

  • 我非常怀疑您是否可以使用样式表来实现它。当您单击箭头时,样式表无法更改滚动条句柄的状态。为此,您可能必须继承 QScrollBar 并自己进行绘画。

标签: python qt pyqt pyqt5


【解决方案1】:

我不知道如何使用样式表来实现它。

我创建了三个 qss 文件。

a.qss

    QScrollBar:vertical{
    background: black;
    width: 10px;
}

b.qss

    QScrollBar:vertical{
    background: black;
    width: 10px;
}


QScrollBar::add-page:vertical{
    background: red;
}

c.qss

    QScrollBar:vertical{
    background: black;
    width: 10px;
}


QScrollBar::sub-page:vertical{
    background: red;
}

和代码:

class Main(QScrollArea):

    def __init__(self):

        super(Main, self).__init__()

        self.resize(300, 200)

        self.index = QWidget()
        self.index.setMinimumHeight(1000)
        self.index.setMinimumWidth(500)


        self.setWidget(self.index)
        self.setWidgetResizable(True)

        with open('a.qss', 'r') as f:
            self.a_text = f.read()
            self.setStyleSheet(self.a_text)
        with open('b.qss', 'r') as f:
            self.b_text = f.read()
        with open('c.qss', 'r') as f:
            self.c_text = f.read()

        # save values.
        self.value = 0
        self.pre_value = 0

        # save pause condition.
        self.pauseCond = True
        self.timer = QTimer()

        self.timer.timeout.connect(self.timerout)
        self.verticalScrollBar().actionTriggered.connect(self.change)
        self.timer.start(300)

    def change(self):
        # if sliding the slider(click and Mouse pulley).

        self.value = self.verticalScrollBar().sliderPosition()

        # if sliding down/right.
        if self.pre_value < self.value:
            self.setStyleSheet(self.b_text)
        # if sliding up/left.
        elif self.pre_value > self.value:
            self.setStyleSheet(self.c_text)

        self.pre_value = self.verticalScrollBar().sliderPosition()
        self.pauseCond = True

    def timerout(self):
        if not self.pauseCond:
            return 1

        # if click or pulley stop.
        if self.verticalScrollBar().sliderPosition() == self.value:
            self.setStyleSheet(self.a_text)
            self.pauseCond = False

我正在学习英语,希望你不要介意。

【讨论】:

    【解决方案2】:

    您实际上可以使用QStyle.hitTestComplexControl(),但它也需要您对滚动条进行子类化。 在下面的示例中,我完全实现了垂直滚动条,您只需填写水平滚动条的基本 css 部分。

    class CustomScrollBar(QtWidgets.QScrollBar):
        def __init__(self, *args, **kwargs):
            QtWidgets.QScrollBar.__init__(self, *args, **kwargs)
            self.baseSheet = '''
                QScrollBar {{
                    width: 45px;
                    margin: 45px 0 45px 0;
                    background: #32CC99;
                }}
    
                QScrollBar::handle {{
                    border: 10px solid grey;
                    background: white;
                    min-height: 10px;
                }}
    
                QScrollBar::add-line:vertical {{
                    border: 2px solid grey;
                    background: none;
                    height: 45px;
                    subcontrol-position: bottom;
                    subcontrol-origin: margin;
                }}
    
                QScrollBar::sub-line:vertical {{
                    border: 2px solid grey;
                    background: none;
                    height: 45px;
                    subcontrol-position: top;
                    subcontrol-origin: margin;
                }}
    
                QScrollBar::up-arrow:vertical {{
                    subcontrol-position: bottom;
                    subcontrol-origin: margin;
                    {upArrow}
                }}
    
                QScrollBar::down-arrow:vertical {{
                    subcontrol-position: bottom;
                    subcontrol-origin: margin;
                    {downArrow}
                }}
    
                QScrollBar::left-arrow:vertical {{
                    subcontrol-position: bottom;
                    subcontrol-origin: margin;
                    {leftArrow}
                }}
    
                QScrollBar::right-arrow:vertical {{
                    subcontrol-position: bottom;
                    subcontrol-origin: margin;
                    {rightArrow}
                }}
                '''
            self.arrowNormal = '''
                    border-top: 5px solid lightgray;
                    border-left: 5px solid lightgray;
                    border-right: 5px solid gray;
                    border-bottom: 5px solid gray;
                '''
            self.arrowPressed = '''
                    border: 5px solid darkgray;
                '''
            self.setStyleSheet(self.baseSheet.format(
                upArrow=self.arrowNormal, 
                downArrow=self.arrowNormal, 
                leftArrow=self.arrowNormal, 
                rightArrow=self.arrowNormal))
    
        def mousePressEvent(self, event):
            QtWidgets.QScrollBar.mousePressEvent(self, event)
            opt = QtWidgets.QStyleOptionSlider()
            opt.initFrom(self)
    
            subControl = self.style().hitTestComplexControl(self.style().CC_ScrollBar, opt, event.pos(), self)
            if subControl == self.style().SC_ScrollBarAddLine:
                if self.orientation() == QtCore.Qt.Vertical:
                    downArrow = self.arrowPressed
                    upArrow = leftArrow = rightArrow = self.arrowNormal
                else:
                    rightArrow = self.arrowPressed
                    upArrow = downArrow = leftArrow = self.arrowNormal
            elif subControl == self.style().SC_ScrollBarSubLine:
                if self.orientation() == QtCore.Qt.Vertical:
                    upArrow = self.arrowPressed
                    downArrow = leftArrow = rightArrow = self.arrowNormal
                else:
                    leftArrow = self.arrowPressed
                    rightArrow = upArrow = downArrow = self.arrowNormal
            self.setStyleSheet(self.baseSheet.format(upArrow=upArrow, downArrow=downArrow, leftArrow=leftArrow, rightArrow=rightArrow))
    
        def mouseReleaseEvent(self, event):
            QtWidgets.QScrollBar.mouseReleaseEvent(self, event)
            self.setStyleSheet(self.baseSheet.format(
                upArrow=self.arrowNormal, 
                downArrow=self.arrowNormal, 
                leftArrow=self.arrowNormal, 
                rightArrow=self.arrowNormal))
    
    
    class MyScrollArea(QtWidgets.QScrollArea):
        def __init__(self, parent=None):
            super(MyScrollArea, self).__init__(parent)
            w = QtWidgets.QWidget()
            w.setFixedSize(640, 480)
            self.setWidget(w)
            vScrollBar = CustomScrollBar(QtCore.Qt.Vertical)
            self.setVerticalScrollBar(vScrollBar)
    

    【讨论】:

    • 非常感谢!明天我会尝试测试它:-)
    猜你喜欢
    • 2010-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    • 2019-04-02
    • 2019-11-28
    相关资源
    最近更新 更多