La detección de eventos del ratón no es consistente con el QGraphicsItem personalizado en el gráfico de pyqtgraph.
Modifiqué el método de pintura de un objeto pixmap para que siempre se dibuje escalado como un porcentaje de la altura del widget y centrado alrededor de la coordenada x de la posición en la que se ha colocado.
Sin embargo, los objetos resultantes no detectan correctamente cuando se les hace clic.
En mi ejemplo, gran parte del área debajo de roi1 informa “got me” y no puedo encontrar en ningún lugar que informe “got me” en roi2.
import pyqtgraph as pg
from PyQt5 import QtWidgets, QtGui, QtCore
import numpy as np
from PyQt5.QtCore import Qt
import logging
class ScaleInvariantIconItem(QtWidgets.QGraphicsPixmapItem):
def __init__(self, *args, **kwargs):
self.id = kwargs.pop("id", "dummy")
self.count = 0
super().__init__(*args, **kwargs)
self.setPixmap(QtWidgets.QLabel().style().standardPixmap(QtWidgets.QStyle.SP_FileDialogStart))
self.scale_percent = .25
self._pen = None
def setPen(self, pen):
self._pen = pen
self.update()
def mousePressEvent(self, event: 'QGraphicsSceneMouseEvent') -> None:
print("got me", self.id, self.count)
self.count += 1
def paint(self, painter: QtGui.QPainter, option: 'QStyleOptionGraphicsItem', widget: QtWidgets.QWidget):
h_scene = self.scene().parent().height()
h = self.pixmap().height()
t = painter.transform();
s = (self.scale_percent*h_scene)/h
self.setTransformOriginPoint(self.pixmap().width()/2,0)
painter.save()
painter.setTransform(QtGui.QTransform(s, t.m12(), t.m13(),
t.m21(), s, t.m23(),
t.m31(), t.m32(), t.m33()))
painter.translate(-self.pixmap().width() / 2, 0)
super().paint(painter, option, widget)
if self._pen:
painter.setPen(self._pen)
painter.drawRect(self.pixmap().rect())
painter.restore()
app = QtWidgets.QApplication([])
pg.setConfigOption('leftButtonPan', False)
g = pg.PlotWidget()
g = pg.PlotWidget()
QtWidgets.QGraphicsRectItem
roi = ScaleInvariantIconItem(id=1)
roi2 = ScaleInvariantIconItem(id=2)
roi2.setPos(10,20)
roi2.setPen(pg.mkPen('g'))
vb = g.plotItem.getViewBox()
vb.setXRange(-20,20)
vb.setYRange(-20,20)
g.addItem(roi)
g.addItem(roi2)
g.addItem(roi2)
g.show()
app.exec_()
davy.ai
El problema en este código es que el método
paint
está escalando y desplazando el pixmap, pero no está actualizando el rectángulo delimitador para reflejar el tamaño y posición escalados del elemento. Como resultado, el área clickeable del elemento permanece en su posición y tamaño original, en lugar de estar correctamente escalada y centrada.Para solucionar este problema, el método
boundingRect
del elemento también debe ser actualizado para reflejar el tamaño y posición escalados del elemento. Esto se puede hacer multiplicando el rectángulo original del pixmap por el factor de escalado y desplazando el rectángulo resultante por la posición escalada del elemento.Aquí hay una implementación de ejemplo de los métodos
paint
yboundingRect
actualizados:Con estos cambios, los elementos detectan correctamente los clics en sus posiciones escaladas y centradas.