def _move_to_mouse_position(self, event): opt = QStyleOptionSlider() self.initStyleOption(opt) control = self.style().hitTestComplexControl(QStyle.CC_ScrollBar, opt, event.pos(), self) if (control == QStyle.SC_ScrollBarAddPage or control == QStyle.SC_ScrollBarSubPage): # scroll here gr = self.style().subControlRect(QStyle.CC_ScrollBar, opt, QStyle.SC_ScrollBarGroove, self) sr = self.style().subControlRect(QStyle.CC_ScrollBar, opt, QStyle.SC_ScrollBarSlider, self) if self.orientation() == Qt.Horizontal: pos = event.pos().x() sliderLength = sr.width() sliderMin = gr.x() sliderMax = gr.right() - sliderLength + 1 if self.layoutDirection() == Qt.RightToLeft: opt.upsideDown = not opt.upsideDown else: pos = event.pos().y() sliderLength = sr.height() sliderMin = gr.y() sliderMax = gr.bottom() - sliderLength + 1 self.setValue( QStyle.sliderValueFromPosition( self.minimum(), self.maximum(), pos - sliderMin - sliderLength // 2, sliderMax - sliderMin, opt.upsideDown, ))
def paintEvent(self, event): # based on http://qt.gitorious.org/qt/qt/blobs/master/src/gui/widgets/qslider.cpp painter = QtGui.QPainter(self) style = QApplication.style() for i, value in enumerate([self._low, self._high]): opt = QStyleOptionSlider() self.initStyleOption(opt) # Only draw the groove for the first slider so it doesn't get drawn # on top of the existing ones every time if i == 0: opt.subControls = QStyle.SC_SliderHandle #QtGui.QStyle.SC_SliderGroove | QtGui.QStyle.SC_SliderHandle else: opt.subControls = QStyle.SC_SliderHandle if self.tickPosition() != self.NoTicks: opt.subControls |= QStyle.SC_SliderTickmarks if self.pressed_control: opt.activeSubControls = self.pressed_control opt.state |= QStyle.State_Sunken else: opt.activeSubControls = self.hover_control opt.sliderPosition = value opt.sliderValue = value style.drawComplexControl(QStyle.CC_Slider, opt, painter, self)
def setup_arrow_buttons(self): """ Setup the up and down arrow buttons that are placed at the top and bottom of the scrollarea. """ # Get the height of the up/down arrow of the default vertical # scrollbar : vsb = self.scrollarea.verticalScrollBar() style = vsb.style() opt = QStyleOptionSlider() vsb.initStyleOption(opt) vsb_up_arrow = style.subControlRect(QStyle.CC_ScrollBar, opt, QStyle.SC_ScrollBarAddLine, self) # Setup the up and down arrow button : up_btn = up_btn = QPushButton(icon=ima.icon('last_edit_location')) up_btn.setFlat(True) up_btn.setFixedHeight(vsb_up_arrow.size().height()) up_btn.clicked.connect(self.go_up) down_btn = QPushButton(icon=ima.icon('folding.arrow_down_on')) down_btn.setFlat(True) down_btn.setFixedHeight(vsb_up_arrow.size().height()) down_btn.clicked.connect(self.go_down) return up_btn, down_btn
def mousePressEvent(self, event): """Add snap-to-location handling.""" opt = QStyleOptionSlider() self.initStyleOption(opt) sr = self.style().subControlRect(QStyle.CC_Slider, opt, QStyle.SC_SliderHandle, self) if (event.button() != Qt.LeftButton or sr.contains(event.pos())): super().mousePressEvent(event) return if self.orientation() == Qt.Vertical: half = (0.5 * sr.height()) + 0.5 max_ = self.height() pos = max_ - event.y() else: half = (0.5 * sr.width()) + 0.5 max_ = self.width() pos = event.x() max_ = max_ - 2 * half pos = min(max(pos - half, 0), max_) / max_ val = self.minimum() + (self.maximum() - self.minimum()) * pos val = (self.maximum() - val) if self.invertedAppearance() else val self.setValue(val) event.accept() # Process afterward so it's seen as a drag super().mousePressEvent(event)
def __init__(self, ori, parent=None): """Initialize the slider.""" super().__init__(ori, parent) self._opt = QStyleOptionSlider() self.initStyleOption(self._opt) self._gr = self.style().subControlRect(QStyle.CC_Slider, self._opt, QStyle.SC_SliderGroove, self) self._sr = self.style().subControlRect(QStyle.CC_Slider, self._opt, QStyle.SC_SliderHandle, self) self._precision = 10000 super().valueChanged.connect(self._convert)
def get_scrollbar_groove_rect(self): """Return the area in which the slider handle may move.""" vsb = self.editor.verticalScrollBar() style = QApplication.instance().style() opt = QStyleOptionSlider() vsb.initStyleOption(opt) # Get the area in which the slider handle may move. groove_rect = style.subControlRect(QStyle.CC_ScrollBar, opt, QStyle.SC_ScrollBarGroove, self) return groove_rect
def offset(self): """This property holds the vertical offset of the scroll flag area relative to the top of the text editor.""" vsb = self.editor.verticalScrollBar() style = QApplication.instance().style() opt = QStyleOptionSlider() vsb.initStyleOption(opt) # Get the area in which the slider handle may move. groove_rect = style.subControlRect(QStyle.CC_ScrollBar, opt, QStyle.SC_ScrollBarGroove, self) return groove_rect.y()
def get_scrollbar_position_height(self): """Return the pixel span height of the scrollbar area in which the slider handle may move""" vsb = self.editor.verticalScrollBar() style = vsb.style() opt = QStyleOptionSlider() vsb.initStyleOption(opt) # Get the area in which the slider handle may move. groove_rect = style.subControlRect(QStyle.CC_ScrollBar, opt, QStyle.SC_ScrollBarGroove, self) return float(groove_rect.height())
def mousePressEvent(self, event): event.accept() style = QApplication.style() button = event.button() # In a normal slider control, when the user clicks on a point in the # slider's total range, but not on the slider part of the control the # control would jump the slider value to where the user clicked. # For this control, clicks which are not direct hits will slide both # slider parts if button: opt = QStyleOptionSlider() self.initStyleOption(opt) self.active_slider = -1 for i, value in enumerate([self._low, self._high]): opt.sliderPosition = value hit = style.hitTestComplexControl(style.CC_Slider, opt, event.pos(), self) if hit == style.SC_SliderHandle: self.active_slider = i self.pressed_control = hit self.triggerAction(self.SliderMove) self.setRepeatAction(self.SliderNoAction) self.setSliderDown(True) break if self.active_slider < 0: self.pressed_control = QStyle.SC_SliderHandle self.click_offset = self.__pixelPosToRangeValue( self.__pick(event.pos())) self.triggerAction(self.SliderMove) self.setRepeatAction(self.SliderNoAction) else: event.ignore()
def __pixelPosToRangeValue(self, pos): opt = QStyleOptionSlider() self.initStyleOption(opt) style = QApplication.style() gr = style.subControlRect(style.CC_Slider, opt, style.SC_SliderGroove, self) sr = style.subControlRect(style.CC_Slider, opt, style.SC_SliderHandle, self) if self.orientation() == Qt.Horizontal: slider_length = sr.width() slider_min = gr.x() slider_max = gr.right() - slider_length + 1 else: slider_length = sr.height() slider_min = gr.y() slider_max = gr.bottom() - slider_length + 1 return style.sliderValueFromPosition(self.minimum(), self.maximum(), pos - slider_min, slider_max - slider_min, opt.upsideDown)
def mouseMoveEvent(self, event): if self.pressed_control != QStyle.SC_SliderHandle: event.ignore() return event.accept() new_pos = self.__pixelPosToRangeValue(self.__pick(event.pos())) opt = QStyleOptionSlider() self.initStyleOption(opt) if self.active_slider < 0: offset = new_pos - self.click_offset self._high += offset self._low += offset if self._low < self.minimum(): diff = self.minimum() - self._low self._low += diff self._high += diff if self._high > self.maximum(): diff = self.maximum() - self._high self._low += diff self._high += diff elif self.active_slider == 0: if new_pos >= self._high: new_pos = self._high - 1 self._low = new_pos else: if new_pos <= self._low: new_pos = self._low + 1 self._high = new_pos self.click_offset = new_pos self.update() #self.emit(QtCore.SIGNAL('sliderMoved(int)'), new_pos) self.sliderMoved.emit(new_pos)