I have created a class that inherits from QSlider and I want to draw a picture on the slider (grabber) instead of showing the plain one.
How to do it?
I have created a class that inherits from QSlider and I want to draw a picture on the slider (grabber) instead of showing the plain one.
How to do it?
Answer provided by Viet:
void InheritedSlider::paintEvent(QPaintEvent *event)
{
// uncomment to draw the parent first. Comment out to just ignore it.
//QSlider::paintEvent(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
//painter.translate(width() / 2, height() / 2);
//painter.scale(100 / 200.0, 100 / 200.0);
QPainterPath volPath;
volPath.moveTo(60.0, 40.0);
volPath.arcTo(20.0, 20.0, 40.0, 40.0, 0.0, 360.0);
volPath.moveTo(40.0, 40.0);
volPath.lineTo(40.0, 80.0);
volPath.lineTo(80.0, 80.0);
volPath.lineTo(80.0, 40.0);
volPath.closeSubpath();
painter.drawPath(volPath);
}
A combination of stylesheets and paintEvent
could be used to customize the handle, without reimplementing mouse events.
If the drawing area exceeds the handle's geometry, it will not pick up mouse clicks, therefore I'm using stylesheets to make it the same size as the area being drawn.
Here's an example that widens the handle and makes it a rounded rect, to adjusted it, it's needed to modify both stylesheets and paintEvent
:
#include <QApplication>
#include <QtWidgets>
class MSlider : public QSlider
{
public:
QRect handleRect;
MSlider(QWidget *parent = nullptr)
{
setStyleSheet("QSlider"
"{"
"width: 52px;"
"}"
"QSlider::groove:vertical "
"{"
//border and width are necessary
//adjust them with care
"border: 1px;"
"width: 5px;"
"background: white;"
"}"
"QSlider::add-page:vertical "
"{"
"background: white;"
"}"
"QSlider::sub-page:vertical "
"{"
"background: green;"
"}"
"QSlider::handle:vertical "
"{"
"height: 24px;"
//width does not make a difference
//use margin instead to control width
"margin: -1px -24px;"
"}");
}
protected:
void paintEvent(QPaintEvent *event) override
{
//paint the slider before painting your custom handle or it might cover it
QSlider::paintEvent(event);
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing);
QStyleOptionSlider opt;
initStyleOption(&opt);
//get handle rect
//use qDebug to check it when adjusting stylesheet
handleRect = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
painter.setBrush(Qt::black);
painter.setPen(Qt::black);
painter.drawRoundedRect(handleRect, 5, 5);
}
};
int main(int argc,char*argv[])
{
QApplication a(argc, argv);
MSlider slider;
slider.show();
return a.exec();
}
Result:
Note: This solution is not tested on horizontal sliders.
For more:
You can do it into the paintEvent method of the widget. This allows you to redraw all or only a part of the widget.