2016-07-26 160 views
0

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

这是你如何调整“外观和感觉”你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

问题:

自定义QS后crollBars,他们完美的工作。但是,单击手柄或箭头时,用户不会得到任何视觉反馈。例如,单击箭头将不会导致箭头被按下的视觉反馈。

这里是它应该如何的例子:

enter image description here

+0

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

回答

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 

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

1

实际上,您可以使用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) 
+0

非常感谢!我会尽力明天测试它:-) –