Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make a tip to follow the handler of slider with PyQT?

A simple question, I am looking for a effect in pyqt like this:

Jquery UI slider how to make a box follow the handler?

But those code is JQuery and I am trying to achieve it with PyQT

import sys
from PyQt4 import QtGui, QtCore

class Window(QtGui.QMainWindow):

    def __init__(self):
        super(Window, self).__init__()
        self.setGeometry(50, 50, 500, 500)
        self.setWindowTitle("PyQT example!")
        slider = QtGui.QSlider(self)
        slider.setOrientation(QtCore.Qt.Horizontal)
        slider.move(50, 50)
        slider.valueChanged.connect(self.value_changed)
        self.show()

    def value_changed(self, value):
        QtGui.QToolTip.showText(QtGui.QCursor.pos(), str(value), self)

app = QtGui.QApplication(sys.argv)
GUI = Window()
sys.exit(app.exec_())

This code successfully made tip balloon follow the cursor. Now is it possible to make the tip follow my slider handler?

like image 881
BangZ Avatar asked Jan 08 '23 21:01

BangZ


2 Answers

I like @tmoreau's idea, but it is better to put new logic into a subclass of QSlider:

class TipSlider(QtGui.QSlider):
    def __init__(self, *args, tip_offset=QPoint(0, -45)):
        super(QtGui.QSlider, self).__init__(*args)
        self.tip_offset = tip_offset

        self.style = QtGui.QApplication.style()
        self.opt = QtGui.QStyleOptionSlider()

        self.valueChanged.connect(self.show_tip)
        # self.enterEvent = self.show_tip
        # self.mouseReleaseEvent = self.show_tip

    def show_tip(self, _):
        self.initStyleOption(self.opt)
        rectHandle = self.style.subControlRect(self.style.CC_Slider, self.opt, self.style.SC_SliderHandle)

        pos_local = rectHandle.topLeft() + self.tip_offset
        pos_global = self.mapToGlobal(pos_local)
        QtGui.QToolTip.showText(pos_global, str(self.value()), self)
like image 191
Alexander Lutsenko Avatar answered Jan 10 '23 11:01

Alexander Lutsenko


Your question is not that simple. Here's my not perfect solution:

  1. First, we need to keep track of the QSlider, so you need to replace all slider by self.slider.

  2. From the QSlider, we can extract the rectangle that contains the handle:

    style=self.slider.style()
    opt=QtGui.QStyleOptionSlider()
    self.slider.initStyleOption(opt)
    rectHandle=style.subControlRect(QtGui.QStyle.CC_Slider,opt, QtGui.QStyle.SC_SliderHandle,self)
    
  3. rectHandle is a QRect, and has several method the get a position in pixels.
    You can either can an int with QRect.bottom(), QRect.right()... or a QPoint with QRect.center(), QRect.bottomRight... All position will be relative to the parent widget, here the slider.
    As an example, to get the absolute position of the rectangle's bottom right corner, you can do:

    myPoint=rectHandle.bottomRight()+self.slider.pos()
    
  4. To improve: finding the right position for the tool tip
    Bellow my best attempt, with some magic numbers:

    magicX = 5
    magicY = 15
    
    x = rectHandle.right() + rectHandle.width() + self.slider.pos().x() + magicX
    y = rectHandle.bottom() + rectHandle.height() + self.slider.pos().y() + magicY
    
  5. Of course, we need to show the tooltip at our custom position:

    QtGui.QToolTip.showText(QtCore.QPoint(x,y), str(value), self)
    

NB: All the computing is done in value_changed method.

like image 42
Mel Avatar answered Jan 10 '23 09:01

Mel