Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pyqt Wheel event

I implemented an image browser where I use the wheel event of the mouse to show the next image. The problem is, if the user scrolls too fast, the position value of the scroll wheel jumps over and swallows the values in between. Does anybody know how I can overcome this problem? If I scroll slowly, I get a decreasing value (-1, -2, -3); if I scroll fast I get something like (-1, -5, -6, -11). The problem appears on WindowsXP & 7.

Here is a sample code.

from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys

#############Define MyWindow Class Here ############
class MyWindow(QMainWindow):
##-----------------------------------------
  def __init__(self):
    QMainWindow.__init__(self)
    self.label = QLabel("No data")
    self.label.setGeometry(100, 200, 100, 100)
    self.setCentralWidget(self.label)
    self.setWindowTitle("QMainWindow WheelEvent")
    self.x = 0
##-----------------------------------------
  def wheelEvent(self,event):
    self.x =self.x + event.delta()/120
    print self.x
    self.label.setText("Total Steps: "+QString.number(self.x))
##-----------------------------------------
##########End of Class Definition ##################


def main():
  app = QApplication(sys.argv)
  window = MyWindow()
  window.show()
  return app.exec_()

if __name__ == '__main__':
 main()
like image 768
honeymoon Avatar asked Nov 21 '13 14:11

honeymoon


1 Answers

There does not appear to be any problem here, as Qt is correctly reporting the number of units scrolled by the mouse wheel.

Some mouse drivers support accelerated scrolling, which means that the number of reported scroll units is progressively increased when the wheel is rotated more rapidly. The units are 0.125 of a degree, and most mice have a baseline scroll speed of 120 units per "notch". Acceleration simply multiplies the baseline speed by an increasing factor as the wheel is rotated faster (i.e. 120, 240, 360, etc).

So in a QWheelEvent, the number of "notches" scrolled is calculated by:

    # PyQt5/PySide2
    event.angleDelta().y() // baseline_speed

    # PyQt4/PySide
    event.delta() // baseline_speed 

which is exactly what the example code in the question already does.

if you want to regsiter each "notch/step" separately, you could just use a loop:

    steps = event.angleDelta().y() // 120
    vector = steps and steps // abs(steps) # 0, 1, or -1
    for step in range(1, abs(steps) + 1):
        self.x += vector
        print(self.x)

Or you could ignore the acceleration, and just register the vector for each wheel event:

    delta = event.angleDelta().y()
    self.x += (delta and delta // abs(delta))
    print(self.x)
like image 80
ekhumoro Avatar answered Sep 20 '22 22:09

ekhumoro