How to set a custom style into the QScrollBar of a QScrollArea?
-
I have created a custom
QProxyStyle
"ScrollBarStyle" and im setting it on the vertical scrollbar of a QScrollAreabut the functions
drawControl
/drawComplexControl
never get called, i also tried usingQCommonStyle
, same problem.What I'm missing?
class ScrollBarStyle : public QProxyStyle { public: void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const override { qDebug() << "element: " << element; if (element == CE_ScrollBarSlider) { const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option); if (slider) { } } else { QProxyStyle::drawControl(element, option, painter, widget); } } void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const override { qDebug() << "control: " << control; if (control == CC_ScrollBar && option->state & State_Horizontal) { const QStyleOptionSlider* sliderOption = qstyleoption_cast<const QStyleOptionSlider*>(option); if (sliderOption) { QRect handleRect = subControlRect(control, option, SC_ScrollBarSlider, widget); painter->setBrush(Qt::red); painter->drawRect(handleRect); return; } } QProxyStyle::drawComplexControl(control, option, painter, widget); } }; class ScrollArea : public QScrollArea { Q_OBJECT public: ScrollArea(QWidget* parent = 0) : QScrollArea(parent) { //this->setStyle(new ScrollBarStyle); this->horizontalScrollBar()->setStyle(new ScrollBarStyle); } }
-
@Cesar said in How to set a custom style into the QScrollBar of a QScrollArea?:
void drawControl(ControlElement element, const QStyleOption *option,
QPainter *painter, const QWidget *widget) constI guess override is missing.
void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const override { } void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const override { }
-
@Cesar I tried to replicate this on my end, I have a
QMainWindow
, and adding aScrollArea
to it did not work as you said,drawControl()
did not get called.But it did work when I set its Style in
mainWindow
.TQScrollArea *area = new TQScrollArea(this); area->setStyle(new ScrollBarStyle); //adding this line made it work
Does this work for you?
-
@Abderrahmene_Rayene said in How to set a custom style into the QScrollBar of a QScrollArea?:
TQScrollArea *area = new TQScrollArea(this);
area->setStyle(new ScrollBarStyle); //adding this line made it work
I didnt understand, you applied the style in the
QScrollArea
? or in theQMainWIndow
? -
@Abderrahmene_Rayene even adding it to the QMainWindow it isnt getting called, adding it as
qApp->setStyle()
onlydrawControl
get called, but neverCE_ScrollBarSlider
In this similar question someone mentioned to do exactly what i tried, reimplementing the drawComplexControl.
And in this question he mentioned about needing to reset
Qt::WA_OpaquePaintEvent
to get the style working, but i didn't understand what he mean which "reset". -
-
@Cesar I had an idea, what if the reason it's not getting called is because there is no
scrollBar
to draw, so I added this line inQMainWindow
:area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
and it worked, both functions got called,
drawControl
/drawComplexControl
-
@Abderrahmene_Rayene i already had the flag
ScrollBarAlwaysOn
set on, and im testing with a QScrollArea that the QScrollBar is visible.At my side its still not getting called, even applying the style on the QMainWindow / QScrollArea QScrollBar
-
@Cesar Then there's something else you should mention, because it does call
drawComplex
on my end, after I replicated what you posted, and the ScrollBar is drawn red and without arrows.This is how it looks like:
-
@Abderrahmene_Rayene
You don't put a debug inside theif (sliderOption)
to tell us, but are you saying thatconst QStyleOptionSlider* sliderOption = qstyleoption_cast<const QStyleOptionSlider*>(option);
is returning
nullptr
/so false for theif
? You never get tofprintf(stderr,"innercomplex\n");
? -
@Abderrahmene_Rayene said in How to set a custom style into the QScrollBar of a QScrollArea?:
if (control == CC_ScrollBar && option->state & State_Horizontal)
Where do you (or the OP) get
option->state & State_Horizontal
from? I see Qt::Orientation QStyleOptionSlider::orientation? Do not assumeQStyle::State_Horizontal
is what you need for aQScrollbar
.... -
@JonB OP is using this function:
[override virtual] void QProxyStyle::drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = nullptr) const
which should get called to draw the scrollBar.
As for
State_Horizontal
, it didn't work for me because I was setting the style for the vertical scroll bar, my bad. It works fine with the horizontal scroll bar. So why shouldn't one use it forQScrollBar
.Sorry for the over-editing, I'm replying and testing simultaneously, I have included an image to display the outcome, it works fine, I can't replicate OP's problem.
-
@Abderrahmene_Rayene im not sure if i understood what you did, could you post a reproducible example of the code you're using?
-
@Cesar I had
TQScrollArea
andScrollBarStyle
in a separate header file, but I included them in themainwindow
header so that I don't post 3 files contents.mainwindow.cpp:
#include "mainwindow.h" #include "./ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); TQScrollArea *area = new TQScrollArea(this); QWidget *widget = new QWidget(); widget->setGeometry(0,0,700,400); area->setWidget(widget); area->horizontalScrollBar()->setStyle(new ScrollBarStyle); area->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); area->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); area->setGeometry(0,0,500,300); } MainWindow::~MainWindow() { delete ui; }
mainwindow.h:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QWidget> #include <QScrollArea> #include <QObject> #include <QWidget> #include <QScrollBar> #include <QDebug> #include <QStyleOptionSlider> #include <QPainter> #include <QProxyStyle> class ScrollBarStyle : public QProxyStyle { public: void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const override { fprintf(stderr,"before\n"); if (element == CE_ScrollBarSlider) { fprintf(stderr,"after\n"); const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option); if (slider) { } } else { QProxyStyle::drawControl(element, option, painter, widget); } } void drawComplexControl(ComplexControl control, const QStyleOptionComplex* option, QPainter* painter, const QWidget* widget) const override { fprintf(stderr,"beforecomplex\n"); if (control == CC_ScrollBar && option->state & State_Horizontal) { fprintf(stderr,"aftercomplex\n"); const QStyleOptionSlider* sliderOption = qstyleoption_cast<const QStyleOptionSlider*>(option); if (sliderOption) { fprintf(stderr,"innercomplex\n"); QRect handleRect = subControlRect(control, option, SC_ScrollBarSlider, widget); painter->setBrush(Qt::red); painter->drawRect(handleRect); return; } } QProxyStyle::drawComplexControl(control, option, painter, widget); } }; class TQScrollArea : public QScrollArea { Q_OBJECT public: TQScrollArea(QWidget* parent = 0) : QScrollArea(parent) { this->verticalScrollBar()->setStyle(new ScrollBarStyle); } }; QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H
mainc.cpp
is just the regular autogenerated one, didn't touch it. -
@Abderrahmene_Rayene said in How to set a custom style into the QScrollBar of a QScrollArea?:
As for
State_Horizontal
, it didn't work for me because I was setting the style for the vertical scroll bar, my bad. It works fine with the horizontal scroll bar. So why shouldn't one use it forQScrollBar
.At the time you were saying the condition was not being entered. I didn't say
option->state & State_Horizontal
would not work, I said to check assumption, since there isa specificQStyleOptionSlider::orientation == Qt::Horizontal
for a slider style option.