Search code examples
pythonpyqtqgraphicssceneqgraphicsitemqmouseevent

get mouse position in the QGraphicScene with pixels coordinate


i try to create a program to manipulate images,I want to have the position of the mouse when it is in the Qgraphicscene, but the event of the mouse is not triggered unless I start outside the Qgraphicview, how can i get this position with the coordinates of the image (pixles) and thank you for the help

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.uic import *
from PIL import Image,ImageFilter,ImageQt



import sys
MainUI, _ = loadUiType('app.ui')


class MainApp(QMainWindow, MainUI):
    def __init__(self):
        super(MainApp, self).__init__()
        QMainWindow.__init__(self)
        self.setupUi(self)
  

    def open_image(self):
        img = QFileDialog.getOpenFileName(self, 'Open file',
                                                  'c:\\')
        pixmap = QtGui.QPixmap(img[0])
        self.scene = QtWidgets.QGraphicsScene()
        self.item = QtWidgets.QGraphicsPixmapItem(pixmap)
        self.scene.addItem(self.item)
        self.graphicsView.setScene(self.scene)
        self.image =Image.open(img[0])
       
    def mouseMoveEvent(self,e):
        print(e.pos())

def main():
    app = QApplication(sys.argv)
    windows = MainApp()
    windows.show()
    app.exec_()


if __name__ == '__main__':
    main()

Solution

  • Widgets receive mouse move events only when mouseTracking is enabled (which is disabled by default for most widgets).

    Also, if you want to track the mouse events in a graphics scene, you have to override the scene's mouseMoveEvent or install an event filter.

    Note that I removed the following line in the __init__:

    QMainWindow.__init__(self)
    

    You already called the super().__init()__ in the first line, calling it again is unnecessary.

    class MainApp(QMainWindow, MainUI):
        def __init__(self):
            super(MainApp, self).__init__()
            self.setupUi(self)
    
            # you could set this in QDesigner instead
            self.graphicsView.setMouseTracking(True)
    
        def open_image(self):
            # ...
            self.scene.installEventFilter(self)
    
        def eventFilter(self, source, event):
            if event.type() == QEvent.GraphicsSceneMouseMove:
                item = self.scene.itemAt(event.scenePos(), QTransform())
                if isinstance(item, QGraphicsPixmapItem):
                    # map the scene position to item coordinates
                    map = item.mapFromScene(event.scenePos())
                    print('mouse is on pixmap at coordinates {}, {}'.format(
                        map.x(), map.y()))
            return super().eventFilter(source, event)