Cómo obtener la coordenada de la imagen cargada y no la de la pantalla

Estoy trabajando en un visor de imágenes con un botón que permite obtener la coordenada de una imagen cargada cuando se hace clic en ella. Sin embargo, cuando hago zoom en la imagen y hago clic en ella, obtengo la coordenada de la pantalla en la que se encuentra la pieza de la imagen, independientemente de donde se centra la imagen dentro del cuadrado. Lo que me gustaría obtener es la coordenada de la imagen cargada donde se hace clic. Esto significa que si el fragmento de imagen en la pantalla es zoom o se desplaza (arriba / abajo o derecha / izquierda), la coordenada debe adaptarse en consecuencia. Puede ser una pregunta fácil con una respuesta fácil, sin embargo, estoy atascado por más de una semana en ese problema a pesar de haber intentado entender la documentación del sitio web de Qt sin éxito

Por ejemplo traté de reemplazar la línea

self.photo_clicked.emit(QtCore.QPoint(event.pos()))

por

self.photo_clicked.emit(QtCore.QPoint(QGraphicsView.mapFromScene(event.pos())))

pero me da ese error:

 TypeError: descriptor 'mapFromScene' requires a 'PySide2.QtWidgets.QGraphicsView' object but received a 'PySide2.QtCore.QPoint' 

Aquí está el script (parte de él está inspirado en este ejemplo ):

 from PySide2.QtWidgets import (QWidget, QApplication, QSlider, QGraphicsView, QGraphicsScene, QVBoxLayout) from PySide2.QtGui import QPainter, QColor from PySide2 import QtCore, QtWidgets, QtGui from PySide2.QtOpenGL import * from PySide2.QtCore import * from PySide2.QtGui import * import sys image_path_str='image.jpg' class View(QGraphicsView): photo_clicked = QtCore.Signal(QtCore.QPoint) def __init__(self, parent): super(View, self).__init__() self.scene = QtWidgets.QGraphicsScene(self) self.photo = QtWidgets.QGraphicsPixmapItem() self.scene.addItem(self.photo) pixmap = QtGui.QPixmap(image_path_str) self.photo.setPixmap(pixmap) self.setScene(self.scene) self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag) def Hand_drag(self): self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag) def pixel_pointer(self): self.setDragMode(QtWidgets.QGraphicsView.NoDrag) def mousePressEvent(self, event): if self.photo.isUnderMouse(): self.photo_clicked.emit(QtCore.QPoint(event.pos())) super(View, self).mousePressEvent(event) class Window(QWidget): def __init__(self): super(Window, self).__init__() self.view = View(self) self.btn_hand_drag = QtWidgets.QCheckBox("Hand drag", self) self.btn_hand_drag.clicked.connect(self.view.Hand_drag) self.btn_hand_drag.clicked.connect(self.btn_hand_drag_uncheck_others) self.btn_pix_info1 = QtWidgets.QCheckBox("Point 1", self) self.btn_pix_info1.clicked.connect(self.view.pixel_pointer) self.btn_pix_info1.clicked.connect(self.btn_pix_info1_drag_uncheck_other) self.editPixInfo1 = QtWidgets.QLineEdit(self) self.editPixInfo1.setReadOnly(True) self.btn_pix_info2 = QtWidgets.QCheckBox("Point 2", self) self.btn_pix_info2.clicked.connect(self.view.pixel_pointer) self.btn_pix_info2.clicked.connect(self.btn_pix_info2_drag_uncheck_other) self.editPixInfo2 = QtWidgets.QLineEdit(self) self.editPixInfo2.setReadOnly(True) self.view.photo_clicked.connect(self.photo_clicked) slider = QSlider(Qt.Horizontal, self) slider.setRange(1, 500) slider.setValue(100) slider.valueChanged[int].connect(self.zoom) vbox = QVBoxLayout() vbox.addWidget(self.btn_hand_drag) vbox.addWidget(self.btn_pix_info1) vbox.addWidget(self.editPixInfo1) vbox.addWidget(self.btn_pix_info2) vbox.addWidget(self.editPixInfo2) vbox.addWidget(self.view) vbox.addWidget(slider) self.setLayout(vbox) self.setWindowTitle("Image viewer") self.setGeometry(200, 200, 1000, 800) def zoom(self, value): val = value / 100 self.view.resetTransform() self.view.scale(val, val) def btn_hand_drag_uncheck_others(self): self.btn_pix_info1.setChecked(False) self.btn_pix_info2.setChecked(False) def btn_pix_info1_drag_uncheck_other(self): self.btn_hand_drag.setChecked(False) self.btn_pix_info2.setChecked(False) def btn_pix_info2_drag_uncheck_other(self): self.btn_hand_drag.setChecked(False) self.btn_pix_info1.setChecked(False) def photo_clicked(self, pos): if self.btn_pix_info1.isChecked(): self.editPixInfo1.setText('%d, %d' % (pos.x(), pos.y())) if self.btn_pix_info2.isChecked(): self.editPixInfo2.setText('%d, %d' % (pos.x(), pos.y())) app = QApplication.instance() if app is None: app = QApplication([]) w = Window() w.show() w.raise_() app.exec_() 

Cuando hace zoom y presiona un píxel, esto puede representar un conjunto de píxeles o viceversa, creo que lo entiende porque mostrar la imagen es una muestra más baja o más alta, según sea el caso. Así que al final, sea lo que sea, obtendrás un píxel que no va a ser ideal, pero muy cercano. Yendo al punto, considerando que en la implementación de @ekhumuro no hay una escalada de los ítems, es correcto usar la posición del mouse con respecto al sistema de coordenadas del ítem y no a la escena, ya que el ítem puede moverse, de modo que La solución general considerando que el artículo no se transforma es:

 def mousePressEvent(self, event): if self._photo.isUnderMouse(): p = self._photo.mapToItem(self._photo, self.mapToScene(event.pos())) self.photoClicked.emit(p.toPoint()) super(PhotoViewer, self).mousePressEvent(event)