Search code examples
pythonpython-3.xqtstylesheetspyside2

How To Make Scrollbar Handle Clickable After Styling?


I'm making a GUI for a client and I'm using Qt for Python 3.6 (PySide2, not PyQt). I have a QTableWidget that reads a bunch of data, which makes the scrollbar appear. My client wants a custom GUI style, so I've been using Qt's setStyleSheet() functions.

I've run into an issue where setting the style on the scrollbar to remove the arrow buttons resizes the handle (as you'd expect) and allows it to move over the area where the arrow buttons used to be. However, if my mouse is in those areas, I can't click on the scrollbar.

enter image description here

The green circles are where the arrow buttons would typically be, the red bar is my scrollbar handle. If my mouse is in the green circles, I can't click on the scrollbar's handle. This becomes a big problem if the scrollbar would become smaller than the button sizes, meaning I'd have to use the scroll wheel to get it out of the area before being able to click on it. While I can fix that issue by giving the handle a minimum height/width, it's also a pretty bad user experience when you can't click certain areas of the scrollbar...

Here is my style sheet:

* {
    color:white;
    }

QWidget {
    background-color:#333;
}

QGroupBox, QGroupBox QLabel {
    background-color:#4c4c4c;
}

QLineEdit {
    background-color:white;
    color:black;
}

QComboBox, QPushButton {
    background-color:maroon;
}

QToolTip {
    border:3px solid maroon;
    padding:5px;
    font-size:16px;
    background-color:#333;
}

QTableWidget {
    color:black;
    background-color:white;
    alternate-background-color:#ffd6d6;
    gridline-color:#4c4c4c;
    selection-background-color:maroon;
}

QHeaderView::section {
    padding:3px;
    text-align:center;
}

QScrollBar::handle {
    background-color:maroon;
    border-radius:6px;
    border: 2px solid #d10000;
    min-width:25px;
    min-height:25px;
}

QScrollBar::left-arrow:horizontal, QScrollBar::right-arrow:horizontal, 
QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
    border: none;
    background: none;
    color: none;
}

QScrollBar::add-line, QScrollBar::sub-line {
    border:none;
    background-color:none;
}

I'm pretty new to using Qt style sheets, so I'm wondering if I'm not missing something. Most answers I've managed to find only say to do what I've already done in the 3 last styles. Does anyone know what the issue might be?


Solution

  • After putting it aside for about a week, I've finally had to sit down and fix this issue.

    For those with the same problem who're also scratching their heads at the answer to this question: Hide QScrollBar arrows, I've found a pretty obvious fix, now that I think about it.

    While the following style sheet does in fact hide the arrow buttons, it does not remove them. Which is obvious in practice, since with further testing, clicking the areas still moved the handle as if I were clicking on the arrow buttons.

    QScrollBar::left-arrow:horizontal, QScrollBar::right-arrow:horizontal, 
    QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
        border: none;
        background: none;
        color: none;
    }
    
    QScrollBar::add-line, QScrollBar::sub-line {
        border:none;
        background-color:none;
    }
    

    The solution is pretty simple: The arrow buttons don't appear to share a style with the rest of the scrollbar (since the scrollbar is separated into sub-styles). This means doing something like setting the width and height properties of the arrow buttons to 0px will make it so you can click on the handle.

    note: For good measure, I've also set the add-line and sub-line properties to 0px.

    QScrollBar::left-arrow:horizontal, QScrollBar::right-arrow:horizontal, 
    QScrollBar::add-page:horizontal, QScrollBar::sub-page:horizontal {
        border: none;
        background: none;
        color: none;
        width: 0px;
        height: 0px;
    }
    
    QScrollBar::add-line, QScrollBar::sub-line {
        border:none;
        background-color:none;
        width: 0px;
        height: 0px;
    }