PyQt mouse events for QGraphicsView

waspinator picture waspinator · Jul 26, 2013 · Viewed 7.9k times · Source

I'm trying to get the coordinates of various mouse events from a QGraphicsView, but I can't figure out how to trigger them. In the end, I want to add a picture to the graphicsView and then draw on top of it.

Ideally I would want the coordinates to have an origin in the top left

0,0--------------------
|
|
|
|
|
|
|          

test.py

import sys
from PyQt4 import QtCore, QtGui, uic


class test(QtGui.QMainWindow):

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.ui = uic.loadUi('test.ui', self)

        self.connect(self.ui.graphicsView, QtCore.SIGNAL("mousePressEvent()"), self.mouse_pressed)
        self.connect(self.ui.graphicsView, QtCore.SIGNAL("mouseMoveEvent()"), self.mouse_moved)
        self.connect(self.ui.graphicsView, QtCore.SIGNAL("mouseReleaseEvent()"), self.mouse_released)

        self.ui.show()

    def mouse_pressed(self):
        p = QtGui.QCursor.pos()
        print "pressed here: " + p.x() + ", " + p.y()

    def mouse_moved(self):
        p = QtGui.QCursor.pos()
        print "moved here: " + p.x() + ", " + p.y()

    def mouse_released(self):
        p = QtGui.QCursor.pos()
        print "released here: " + p.x() + ", " + p.y()


def main():
    app = QtGui.QApplication(sys.argv)
    ui = test()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

test.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MainWindow</class>
 <widget class="QMainWindow" name="MainWindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>800</width>
    <height>600</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>MainWindow</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QGraphicsView" name="graphicsView"/>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>800</width>
     <height>22</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

EDIT:

this seems to work. the ellipse is no longer moveable, as the click event seems to take over. any ideas?

import sys
from PyQt4 import QtCore, QtGui, uic


class graphicsScene(QtGui.QGraphicsScene):
    def __init__ (self, parent=None):
        super(graphicsScene, self).__init__ (parent)

    def mousePressEvent(self, event):
        position = QtCore.QPointF(event.scenePos())
        print "pressed here: " + str(position.x()) + ", " + str(position.y())
        self.update()

    def mouseMoveEvent(self, event):
        position = QtCore.QPointF(event.scenePos())
        print "moved here: " + str(position.x()) + ", " + str(position.y())
        self.update()

    def mouseReleaseEvent(self, event):
        position = QtCore.QPointF(event.scenePos())
        print "released here: " + str(position.x()) + ", " + str(position.y())
        self.update()


class test(QtGui.QMainWindow):

    def __init__(self):
        QtGui.QMainWindow.__init__(self)
        self.ui = uic.loadUi('test.ui', self)

        self.scene = graphicsScene()
        self.ui.graphicsView.setScene(self.scene)

        pen = QtGui.QPen(QtCore.Qt.red)
        brush = QtGui.QBrush(QtCore.Qt.blue)
        e = self.scene.addEllipse(10,10,100,100, pen, brush)
        e.setFlag(QtGui.QGraphicsItem.ItemIsMovable, True)

        self.ui.show()


def main():
    app = QtGui.QApplication(sys.argv)
    ui = test()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Answer

Pavel Strakhov picture Pavel Strakhov · Jul 27, 2013

mousePressEvent and other methods are not slots. You can't use connect on those methods. You need to install an event filter on your view's viewport() and catch events in your widget's eventFilter method.

See Event Filters.