1

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()
Ay Men
  • 90
  • 7

1 Answers1

2

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)
musicamante
  • 41,230
  • 6
  • 33
  • 58
  • please you can explain this solution to me, it works very well but i want to understand how it works, and if you can give me a source to go further, and thank you very much – Ay Men Jul 05 '20 at 20:35
  • You can read more about [event filters](https://doc.qt.io/archives/qt-4.8/eventsandfilters.html#event-filters) in the official documentation (it's C++ oriented, but 99% of the concepts and function/class names are the same for PyQt). Basically, the event filter "intercepts" events that are going to be processed by the object for which it's installed (the graphics scene, in this case), by implementing it you can check for specific events and act accordingly: in this case I'm detecting a GraphicsSceneMouseMove, so I can get its coordinates, and map them to the item. – musicamante Jul 05 '20 at 20:53