Issue
I'm having trouble finding the correct centre of the QScrollBar's slider (I need to stick a text widget to it to display the position of the slider). I tried normalising the slider's position by dividing it by the document width, then scaling it by it's width(). But that's not accurate because the scroll bar's decorations and buttons are not taken into account. So the label wanders off as you drag and won't stick to the centre. Below is my current code which somehow need to take into account the QScrollBar's buttons, frames etc to find the correct start and end position of the scroll area. Could somebody help please?
import sys
from PySide.QtGui import *
from PySide.QtCore import *
class PageScroller(QScrollBar):
'''Set the total number of pages.'''
def __init__(self, parent=None):
super(PageScroller, self).__init__(parent)
self.pageIndicator = QLabel('|', parent)
self.valueChanged.connect(self.updateSlider)
self.setOrientation(Qt.Orientation.Horizontal)
self.setPageStep(1)
def updateSlider(self, event):
scrollAreaWidth = self.maximum() - self.minimum() + self.pageStep()
sliderPos = (self.sliderPosition() + self.pageStep()/2.0) / float(scrollAreaWidth) * self.width()
indicatorPos = QPoint(sliderPos - self.pageIndicator.width()/2, -self.pageIndicator.height())
self.pageIndicator.move(self.mapToParent(indicatorPos))
self.update()
if __name__ == '__main__':
app = QApplication(sys.argv)
#app.setStyle('plastique') # tyhis makes the sliding more obvious
mainWindow = QWidget()
layout = QVBoxLayout(mainWindow)
s = PageScroller(mainWindow)
layout.addWidget(s)
mainWindow.resize(400, 100)
mainWindow.show()
sys.exit(app.exec_())
Solution
It would be really hard, like you have discovered, to properly map a pixel range of the slider portion, while accounting for the various style differences between platforms. Too many factors (extra buttons on the left and right, the slider size itself, ...)
This is really obscure, and it takes a bit of hunting to find it out, but you actually need to query for the SubControl of the QScrollBar. What you can get back is a QRect of the scroll handle:
def resizeEvent(self, event):
super(PageScroller, self).resizeEvent(event)
self.updateSlider()
def updateSlider(self, val=None):
opt = QStyleOptionSlider()
self.initStyleOption(opt)
style = self.style()
handle = style.subControlRect(style.CC_ScrollBar, opt,
style.SC_ScrollBarSlider)
sliderPos = handle.center()
sliderPos.setY(-self.pageIndicator.height())
self.pageIndicator.move(self.mapToParent(sliderPos))
- You first have to create an empty QStyleOptionSlider, and have it populated with the current state of your PageScroller.
- Then you have to take the style from the PageScroller, and use subControlRect to query the subcontrol of a
ComplexControl ScrollBar
type, for theSubControl ScrollBarSlider
type. It uses the opts to return you a QRect of the slider - Then you can map as normal and move the pageIndicator
I added a resizeEvent
to also properly place the indicator at first show, and during any resizes of the widget.
Answered By - jdi
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.