PDA

View Full Version : Problems customizing QSlider



Antrax
5th October 2006, 16:48
This is a copy of a message posted to the qt-interest list. The list was of no help.

I've been working on a class to implement a QSlider with a custom pixmap
instead of the default handle graphics. Inheriting QSilder and overriding
the paintEvent method seemed too clunky, so instead I opted to create a new
style and override the drawComplexControl method. That basically works, with
two problems:
1) The pixmap is clipped by the QSlider boundary, despite me overriding the
contentsRect() method of QSLider with my own pixmap-aware implementation.
2) For some reason, dragging the slider only works when I use some other
combination of mouse buttons that's not just LMB. So if I press right+left,
I can drag just find, but just left mouse button alone doesn't do anything.
This is odd because I haven't touched mouseEvents.

Any help will be appreciated.

jacek
5th October 2006, 17:40
Maybe it's because QSlider doesn't know the exact size of your pixmap?

Antrax
8th October 2006, 09:27
That's what I'm guessing, but what do I need to override to tell it that? None of the pixelMetrics seem relevant.

jpn
8th October 2006, 10:06
How about QStyle::pixelMetric(QStyle::PM_SliderThickness)? Seems to be used in QSlider::sizeHint(). You can dig a lot of valuable information by taking a look at QSlider sources..

Antrax
8th October 2006, 15:06
Nice catch, thanks. I assumed that metric referred to the width of the groove the slider moved in. Apparently, it doesn't :)

Antrax
9th October 2006, 16:56
That worked like a charm. Now, however, there's still some horizontal clipping. I've tried reimplementing QStyle::PM_SliderLength and QStyle::PM_SliderSpaceAvailable and neither helped. What metric am I overlooking this time?

jpn
9th October 2006, 16:59
This is just a guess, but maybe QStyle::sizeFromContents(QStyle::CT_Slider)? I see it being used in QSlider::sizeHint().

Antrax
9th October 2006, 19:44
Nope, no luck this time :)

jpn
9th October 2006, 20:23
About the "horizontal clipping".. what's the orientation of the slider? Mind giving out a screenshot of what you've achieved so far? :)
And what about QStyle::subControlRect(QStyle::SC_SliderHandle), have you taken care of that? Is your style using this area for painting the handle pixmap?

Antrax
10th October 2006, 14:28
from drawComplexControl:

QStyleOptionSlider NewOptions(*StyleOptions);
NewOptions.subControls &= ~SC_SliderHandle;
DefaultStyle->drawComplexControl(control, &NewOptions, painter, widget);

//manually drawing the handle
QRect HandlePos = DefaultStyle->subControlRect(CC_Slider, option, SC_SliderHandle);
QRect PicRect = sliderPicture->rect();

PicRect.moveCenter(HandlePos.center());
painter->drawPixmap(PicRect, *sliderPicture, sliderPicture->rect());

from pixelMetric:

QStyle* DefaultStyle = QApplication::style();

if (QStyle::PM_SliderSpaceAvailable == metric)
return DefaultStyle->pixelMetric(metric, option, widget) - sliderPicture->width();

if (QStyle::PM_SliderThickness == metric)
return sliderPicture->height();

return DefaultStyle->pixelMetric(metric, option, widget);

The slider is horizontal, so when the handle is at one of the extreme edged, the pixmap is clipped. I'll post a picture later today. Thanks!

jpn
11th October 2006, 17:44
This is from src/gui/widget/qslider.cpp:



/*!
\reimp
*/
QSize QSlider::sizeHint() const
{
Q_D(const QSlider);
ensurePolished();
const int SliderLength = 84, TickSpace = 5;
QStyleOptionSlider opt = d->getStyleOption();
int thick = style()->pixelMetric(QStyle::PM_SliderThickness, &opt, this);
if (d->tickPosition & TicksAbove)
thick += TickSpace;
if (d->tickPosition & TicksBelow)
thick += TickSpace;
int w = thick, h = SliderLength;
if (d->orientation == Qt::Horizontal) {
w = SliderLength;
h = thick;
}
return style()->sizeFromContents(QStyle::CT_Slider, &opt, QSize(w, h), this).expandedTo(QApplication::globalStrut());
}

/*!
\reimp
*/
QSize QSlider::minimumSizeHint() const
{
Q_D(const QSlider);
QSize s = sizeHint();
QStyleOptionSlider opt = d->getStyleOption();
int length = style()->pixelMetric(QStyle::PM_SliderLength, &opt, this);
if (d->orientation == Qt::Horizontal)
s.setWidth(length);
else
s.setHeight(length);
return s;
}


This is the size a QSlider requests when being in a layout. If you already have taken care of QStyle::pixelMetric(QStyle::PM_SliderLength), the only choice left is QStyle::sizeFromContents(QStyle::CT_Slider). You should somehow make sure there is enough padding space at the ends, not just test if the pixmap would fit into the given size.

Antrax
11th October 2006, 20:29
I have to say I'm completely stumped. I've read some style files and qslider and qabstractslider, and I've tried overriding every single thing they use, and all to no avail.
So I went for a cop-out and implemented a PictureSlider class, overrided the setMaximum and setMinimum to add a little extra, and manually kept the slider just a little before the groove edge by catching valueChanged. It's not the way this thing's supposed to work, but at least it works :o

pratik041
8th November 2011, 04:53
Antrax can you please post your whole code. I am also trying to make custom slider using pixmap but i am not getting the proper output.

kinjalp
20th December 2011, 07:00
I have same problem I want to change vertical scrollbar thickness but I didn't change it....

Can You help me out for the same???


kinjal.