Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PyQt4 MouseMove event without MousePress

I need to catch when a User moves the mouse over the GUI, but not when they're holding down the mouse button (which would do something different).

I can't find any conveniant method to do this, except to periodically find the mouse position and check it to it's previous position... Which would suck.

The mouseMoveEvent is only called when the mouse is moved whilst the left mouse button is pressed, unless ofcourse the widget has 'mouse tracking'. Mouse tracking is not an option for me, because the GUI must behave differently when the mouse is moved and the left mouse button is pressed.

Are there any inbuilt methods to do this? (or just any clever ideas?)

eg: Is there a way to check if the left mouse button is being pressed at any time?
Or a 'mouse hover' event that can be applied to a QRect (coordinates)?

Muchas gracias.


Windows 7 (32)
python 2.7
PyQt4

like image 774
Anti Earth Avatar asked Oct 20 '11 00:10

Anti Earth


4 Answers

The most straightforward way to do this is to install an event filter on qApp:

from PyQt4 import QtGui, QtCore

class Window(QtGui.QMainWindow):
    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        widget = QtGui.QWidget(self)
        layout = QtGui.QVBoxLayout(widget)
        self.edit = QtGui.QLineEdit(self)
        self.list = QtGui.QListWidget(self)
        layout.addWidget(self.edit)
        layout.addWidget(self.list)
        self.setCentralWidget(widget)

    def eventFilter(self, source, event):
        if event.type() == QtCore.QEvent.MouseMove:
            if event.buttons() == QtCore.Qt.NoButton:
                pos = event.pos()
                self.edit.setText('x: %d, y: %d' % (pos.x(), pos.y()))
            else:
                pass # do other stuff
        return QtGui.QMainWindow.eventFilter(self, source, event)

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    win = Window()
    win.show()
    app.installEventFilter(win)
    sys.exit(app.exec_())
like image 193
ekhumoro Avatar answered Nov 14 '22 02:11

ekhumoro


call setMouseTracking(True) method first. Then mouseMoveEvent will be fired without any button pressed.

like image 34
HYRY Avatar answered Nov 14 '22 00:11

HYRY


As people have said, the correct approach seems to be to call setMouseTracking(True) on the widget. What I'd like to add is that, having done this, you can distinguish between a mouse motion and a mouse drag as follows:

def mouseMoveEvent(self, event):
    if event.buttons() == QtCore.Qt.NoButton:
        print "Simple mouse motion"
    elif event.buttons() == QtCore.Qt.LeftButton:
        print "Left click drag"
    elif event.buttons() == QtCore.Qt.RightButton:
        print "Right click drag"
like image 3
MarcTheSpark Avatar answered Nov 14 '22 01:11

MarcTheSpark


It seems you've misunderstood what mouseTracking does. It only causes mouseMoveEvent to be fired, nothing else. In other words, it's exactly what you need.

Check the event's buttons() to see if any button was pressed:

For mouse move events, this is all buttons that are pressed down.

like image 2
Petr Viktorin Avatar answered Nov 14 '22 00:11

Petr Viktorin