Adding padding to QSlider does not work on Fusion style
-
Hi,
We are trying to develop a QSlider derivative which shows labels below the ticks.
We are currently only supporting a horizontal slider.
To avoid clipping the labels of the first and last tick, we added some margin/padding to the left and right of the original slider.
To do this, we noted in the QSlider implementation of
paintEvent
(line 282) that the rectangle is derived frominitStyleOption
before it is passed toQStylePainter.drawComplexControl
for the actual drawing.We have used this mechanism to add the margin we require by re-implementing
initStyleOption
in our PySide code:def initStyleOption(self, option): """Re-implement to provide space for the text below the slider, and the margin to the left and right (as usual, from the perspective of horizontal sliders). This method is called by the default paintEvent. Initialise as normal, then restore the normal height (observed on Windows) to trick QSlider.paintEvent into ignoring the true height. This leaves room for us to draw the labels below. """ super().initStyleOption(option) option.rect.setHeight(27) option.rect.adjust(+self.margin, 0, -self.margin, 0)
On my default platform-style ("windowsvista") this work nicely:
However, with the style Fusion the ticks and the central blue spine are shifted:
We believe this is because when the style draws the ticks, it does not use the rectangle of the
option
variable defined above, but uses the rectangle of the widget. Please see QFusionStyle::drawComplexControl:- Line 1884 for the start of the method.
- Line 2766 for the start of the slider part.
- Line 2870 for the start of the tick-drawing code.
To replicate the code of the "vista" style, we tend to think that on line 2894 the code should not use
slider->rect.width()
butoption->rect.width()
.Questions:
- Could this be considered a bug?
- Can we achieve the required padding effect in a way that is better/more robust?
Thanks in advance for any hints...
Best regards, pietro.
-
Hi,
We are trying to develop a QSlider derivative which shows labels below the ticks.
We are currently only supporting a horizontal slider.
To avoid clipping the labels of the first and last tick, we added some margin/padding to the left and right of the original slider.
To do this, we noted in the QSlider implementation of
paintEvent
(line 282) that the rectangle is derived frominitStyleOption
before it is passed toQStylePainter.drawComplexControl
for the actual drawing.We have used this mechanism to add the margin we require by re-implementing
initStyleOption
in our PySide code:def initStyleOption(self, option): """Re-implement to provide space for the text below the slider, and the margin to the left and right (as usual, from the perspective of horizontal sliders). This method is called by the default paintEvent. Initialise as normal, then restore the normal height (observed on Windows) to trick QSlider.paintEvent into ignoring the true height. This leaves room for us to draw the labels below. """ super().initStyleOption(option) option.rect.setHeight(27) option.rect.adjust(+self.margin, 0, -self.margin, 0)
On my default platform-style ("windowsvista") this work nicely:
However, with the style Fusion the ticks and the central blue spine are shifted:
We believe this is because when the style draws the ticks, it does not use the rectangle of the
option
variable defined above, but uses the rectangle of the widget. Please see QFusionStyle::drawComplexControl:- Line 1884 for the start of the method.
- Line 2766 for the start of the slider part.
- Line 2870 for the start of the tick-drawing code.
To replicate the code of the "vista" style, we tend to think that on line 2894 the code should not use
slider->rect.width()
butoption->rect.width()
.Questions:
- Could this be considered a bug?
- Can we achieve the required padding effect in a way that is better/more robust?
Thanks in advance for any hints...
Best regards, pietro.
Could this be considered a bug?
Yes, looks like it.
Can we achieve the required padding effect in a way that is better/more robust?
Adjusting the rectangle in paintEvent seems a bit weird anyway. If you add margins just to painting the visual wouldn't match the mouse position in events when trying to grab the handle.
Perhaps a simpler solution would be to just put the slider in a QWidget derived class. Put it in a layout with margins to accommodate the numbers and do the painting in that widget. It would also be safer from any style quirks like this. -
Could this be considered a bug?
Yes, looks like it.
Can we achieve the required padding effect in a way that is better/more robust?
Adjusting the rectangle in paintEvent seems a bit weird anyway. If you add margins just to painting the visual wouldn't match the mouse position in events when trying to grab the handle.
Perhaps a simpler solution would be to just put the slider in a QWidget derived class. Put it in a layout with margins to accommodate the numbers and do the painting in that widget. It would also be safer from any style quirks like this.Hi @Chris-Kawa
Thanks for the reply. I omitted that comment from the code for clarify, but the mouse tracking follows theinitStyleOption
, so this works automatically.
Embedding in a QWidget seems a good idea, but we'd lose the API-compatibility with QSlider, and we can't use it in Qt Designer. I think it would still be useful if we can find a solution without the embedding. -
Hi @Chris-Kawa
Thanks for the reply. I omitted that comment from the code for clarify, but the mouse tracking follows theinitStyleOption
, so this works automatically.
Embedding in a QWidget seems a good idea, but we'd lose the API-compatibility with QSlider, and we can't use it in Qt Designer. I think it would still be useful if we can find a solution without the embedding.@wpietro hi,
It's a bit more work but you can use your widget in Qt Designer.
For fixing the issue, you should check the bug report system to see if there's already something about it and if not, open a new ticket.
You can also rebuild just the plugin with your change to test it. -
@wpietro hi,
It's a bit more work but you can use your widget in Qt Designer.
For fixing the issue, you should check the bug report system to see if there's already something about it and if not, open a new ticket.
You can also rebuild just the plugin with your change to test it.