2

I can't figure out how to set a stylesheet to modify the QScrollBar in a QScrollArea.

I've first tried:

scrollarea = QScrollArea()
scrollarea.verticalScrollBar().setStyleSheet("""
    QScrollBar:horizontal {
        min-width: 240px;
        height: 13px;
    }

    QScrollBar:vertical {
        min-height: 240px;
        width: 13px;
    }

    QScrollBar::groove {
        background: gray;
        border-radius: 5px;
    }

    QScrollBar::handle {
        background: blue;
        border-radius: 5px;
    }

    QScrollBar::handle:horizontal {
        width: 25px;
    }

    QScrollBar::handle:vertical {
        height: 25px;
    }"""
# same for horizontalScrollBar

Then I tried applying the exact same stylesheet directly on the QScrollArea instance, with no success.

Then I tried to define the scrollbar myself :

scrollArea = QScrollArea(self)
verticalScrollBar = QScrollBar(qt.Qt.Vertical, scrollArea)
verticalScrollBar.setStyleSheet(my_stylesheet)
scrollArea.setVerticalScrollBar(verticalScrollBar)

But the exact same stylesheet works on a QSlider (by replacing QScrollBar with QSlider).

PiRK
  • 893
  • 3
  • 9
  • 24

2 Answers2

7

Try it:

import sys
from PyQt5.QtWidgets import QScrollBar, QDialog, QVBoxLayout, QApplication
from PyQt5.QtCore import Qt

class MainWindow(QDialog):
    def __init__(self):
        super().__init__()
        self.createWidgets()

    def createWidgets(self):
        self.layout = QVBoxLayout(self)

        self.scrollbar1 = QScrollBar(Qt.Vertical, self)
        self.scrollbar2 = QScrollBar(Qt.Horizontal, self)

        for widget in [self.scrollbar1, self.scrollbar2]:
            widget.valueChanged.connect(self.test)
            self.layout.addWidget(widget)

    def test(self, event):
        print(self.sender().value())


stylesheet = """
    /* --------------------------------------- QScrollBar  -----------------------------------*/
    QScrollBar:horizontal
    {
        height: 15px;
        margin: 3px 15px 3px 15px;
        border: 1px transparent #2A2929;
        border-radius: 4px;
        background-color: yellow;    /* #2A2929; */
    }

    QScrollBar::handle:horizontal
    {
        background-color: blue;      /* #605F5F; */
        min-width: 5px;
        border-radius: 4px;
    }

    QScrollBar::add-line:horizontal
    {
        margin: 0px 3px 0px 3px;
        border-image: url(:/qss_icons/rc/right_arrow_disabled.png);
        width: 10px;
        height: 10px;
        subcontrol-position: right;
        subcontrol-origin: margin;
    }

    QScrollBar::sub-line:horizontal
    {
        margin: 0px 3px 0px 3px;
        border-image: url(:/qss_icons/rc/left_arrow_disabled.png);
        height: 10px;
        width: 10px;
        subcontrol-position: left;
        subcontrol-origin: margin;
    }

    QScrollBar::add-line:horizontal:hover,QScrollBar::add-line:horizontal:on
    {
        border-image: url(:/qss_icons/rc/right_arrow.png);
        height: 10px;
        width: 10px;
        subcontrol-position: right;
        subcontrol-origin: margin;
    }


    QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on
    {
        border-image: url(:/qss_icons/rc/left_arrow.png);
        height: 10px;
        width: 10px;
        subcontrol-position: left;
        subcontrol-origin: margin;
    }

    QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal
    {
        background: none;
    }


    QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal
    {
        background: none;
    }

    QScrollBar:vertical
    {
        background-color: #2A2929;
        width: 15px;
        margin: 15px 3px 15px 3px;
        border: 1px transparent #2A2929;
        border-radius: 4px;
    }

    QScrollBar::handle:vertical
    {
        background-color: red;         /* #605F5F; */
        min-height: 5px;
        border-radius: 4px;
    }

    QScrollBar::sub-line:vertical
    {
        margin: 3px 0px 3px 0px;
        border-image: url(:/qss_icons/rc/up_arrow_disabled.png);
        height: 10px;
        width: 10px;
        subcontrol-position: top;
        subcontrol-origin: margin;
    }

    QScrollBar::add-line:vertical
    {
        margin: 3px 0px 3px 0px;
        border-image: url(:/qss_icons/rc/down_arrow_disabled.png);
        height: 10px;
        width: 10px;
        subcontrol-position: bottom;
        subcontrol-origin: margin;
    }

    QScrollBar::sub-line:vertical:hover,QScrollBar::sub-line:vertical:on
    {
        border-image: url(:/qss_icons/rc/up_arrow.png);
        height: 10px;
        width: 10px;
        subcontrol-position: top;
        subcontrol-origin: margin;
    }

    QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on
    {
        border-image: url(:/qss_icons/rc/down_arrow.png);
        height: 10px;
        width: 10px;
        subcontrol-position: bottom;
        subcontrol-origin: margin;
    }

    QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical
    {
        background: none;
    }

    QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical
    {
        background: none;
    }
"""

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyleSheet(stylesheet)       # <----
    GUI = MainWindow()
    GUI.resize(300, 200)
    GUI.show()
    sys.exit(app.exec_())

enter image description here


Update

Upload images from a resource file. This way is to convert the res.qrc file in the res_rc.py file through the pyrcc5 file, which can be directly loaded by import.

In a directory, for example images were put images: right_arrow.png, ...

Created a file such as stylesheet.qrc:

 <RCC>
 <qresource prefix="/">
     <file>images/down_arrow.png</file>
     <file>images/down_arrow_disabled.png</file>
     <file>images/up_arrow.png</file>
     <file>images/up_arrow_disabled.png</file>
     <file>images/left_arrow.png</file>
     <file>images/left_arrow_disabled.png</file>
     <file>images/right_arrow.png</file>
     <file>images/right_arrow_disabled.png</file>
 </qresource>
 </RCC>

Convert stylesheet.qrc to stylesheet_rc.py pyrcc5 stylesheet.qrc -o stylesheet_rc.py

Paste into main.py - import stylesheet_rc

Transfer the modules main.py and stylesheet_rc.py to some other directory and run main.py

main.py

import sys
from PyQt5.QtWidgets import QScrollBar, QDialog, QVBoxLayout, QApplication
from PyQt5.QtCore import Qt

import stylesheet_rc                                       # <--------                           

class MainWindow(QDialog):
    def __init__(self):
        super().__init__()
        self.createWidgets()

    def createWidgets(self):
        self.layout = QVBoxLayout(self)

        self.scrollbar1 = QScrollBar(Qt.Vertical, self)
        self.scrollbar2 = QScrollBar(Qt.Horizontal, self)

        for widget in [self.scrollbar1, self.scrollbar2]:
            widget.valueChanged.connect(self.test)
            self.layout.addWidget(widget)

    def test(self, event):
        print(self.sender().value())


stylesheet = """
    /* --------------------------------------- QScrollBar  -----------------------------------*/
    QScrollBar:horizontal
    {
        height: 15px;
        margin: 3px 15px 3px 15px;
        border: 1px transparent #2A2929;
        border-radius: 4px;
        background-color: yellow;    /* #2A2929; */
    }

    QScrollBar::handle:horizontal
    {
        background-color: blue;      /* #605F5F; */
        min-width: 5px;
        border-radius: 4px;
    }

    QScrollBar::add-line:horizontal
    {
        margin: 0px 3px 0px 3px;
        border-image: url(:/images/right_arrow_disabled.png);       /* # <-------- */
        width: 10px;
        height: 10px;
        subcontrol-position: right;
        subcontrol-origin: margin;
    }

    QScrollBar::sub-line:horizontal
    {
        margin: 0px 3px 0px 3px;
        border-image: url(:/images/left_arrow_disabled.png);        /* # <-------- */ 
        height: 10px;
        width: 10px;
        subcontrol-position: left;
        subcontrol-origin: margin;
    }

    QScrollBar::add-line:horizontal:hover,QScrollBar::add-line:horizontal:on
    {
        border-image: url(:/images/right_arrow.png);               /* # <-------- */
        height: 10px;
        width: 10px;
        subcontrol-position: right;
        subcontrol-origin: margin;
    }


    QScrollBar::sub-line:horizontal:hover, QScrollBar::sub-line:horizontal:on
    {
        border-image: url(:/images/left_arrow.png);               /* # <-------- */
        height: 10px;
        width: 10px;
        subcontrol-position: left;
        subcontrol-origin: margin;
    }

    QScrollBar::up-arrow:horizontal, QScrollBar::down-arrow:horizontal
    {
        background: none;
    }


    QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal
    {
        background: none;
    }

    QScrollBar:vertical
    {
        background-color: #2A2929;
        width: 15px;
        margin: 15px 3px 15px 3px;
        border: 1px transparent #2A2929;
        border-radius: 4px;
    }

    QScrollBar::handle:vertical
    {
        background-color: red;         /* #605F5F; */
        min-height: 5px;
        border-radius: 4px;
    }

    QScrollBar::sub-line:vertical
    {
        margin: 3px 0px 3px 0px;
        border-image: url(:/images/up_arrow_disabled.png);        /* # <-------- */
        height: 10px;
        width: 10px;
        subcontrol-position: top;
        subcontrol-origin: margin;
    }

    QScrollBar::add-line:vertical
    {
        margin: 3px 0px 3px 0px;
        border-image: url(:/images/down_arrow_disabled.png);       /* # <-------- */
        height: 10px;
        width: 10px;
        subcontrol-position: bottom;
        subcontrol-origin: margin;
    }

    QScrollBar::sub-line:vertical:hover,QScrollBar::sub-line:vertical:on
    {
        border-image: url(:/images/up_arrow.png);                  /* # <-------- */
        height: 10px;
        width: 10px;
        subcontrol-position: top;
        subcontrol-origin: margin;
    }

    QScrollBar::add-line:vertical:hover, QScrollBar::add-line:vertical:on
    {
        border-image: url(:/images/down_arrow.png);                /* # <-------- */
        height: 10px;
        width: 10px;
        subcontrol-position: bottom;
        subcontrol-origin: margin;
    }

    QScrollBar::up-arrow:vertical, QScrollBar::down-arrow:vertical
    {
        background: none;
    }

    QScrollBar::add-page:vertical, QScrollBar::sub-page:vertical
    {
        background: none;
    }
"""

if __name__ == '__main__':
    app = QApplication(sys.argv)
    app.setStyleSheet(stylesheet)       # <----
    GUI = MainWindow()
    GUI.resize(300, 200)
    GUI.show()
    sys.exit(app.exec_())

enter image description here

Patitotective
  • 35
  • 1
  • 7
S. Nick
  • 12,879
  • 8
  • 25
  • 33
  • 1
    It works for QScrollBar when used directly, but not for a QScrollArea. – PiRK Feb 12 '19 at 15:28
  • It actually works, thanks! I must have introduced an error invalidating the stylesheet, the first time I tried it. Could you please explain the trick used to remove the arrow icons? It seems to be the lines that end with ``...arrow_disabled.png``. Is this an empty image? Can I rely on it to be shipped with all versions of Qt? – PiRK Feb 18 '19 at 08:53
  • I added an update. @PiRK If my answer helps you do not forget to mark my answer as correct. – S. Nick Feb 18 '19 at 11:28
  • Thanks again. I marked your answer as the right one. I did find a much simpler way to hide the arrow icons : https://stackoverflow.com/a/25989355/4494781 – PiRK Feb 18 '19 at 13:34
2

My problem was that the stylesheet for QSlider and QScrollBar have sligthly different syntaxes.

My eventual solution is (to be set either as the QScrollArea stylesheet or as the QApplication stylesheet, depending on the desired scope):

stylesheet = """
    QScrollArea {
        border: none;
    }

    QScrollBar {
        background: gray;
        border-radius: 5px;
    }

    QScrollBar:horizontal {
        height: 13px;
    }

    QScrollBar:vertical {
        width: 13px;
    }

    QScrollBar::handle {
        background: green;
        border-radius: 5px;
    }

    QScrollBar::handle:horizontal {
        height: 25px;
        min-width: 10px;
    }

    QScrollBar::handle:vertical {
        width: 25px;
        min-height: 10px;
    }

    QScrollBar::add-line {
        border: none;
        background: none;
    }

    QScrollBar::sub-line {
        border: none;
        background: none;
    }
    """
PiRK
  • 893
  • 3
  • 9
  • 24