I try to have a rect which moves with the mouse pointer. However, I seem to have a problem with calling the paint method. It either doesn’t draw or creates artifacts. The only clean picture I get is with a forced redraw (zoom the graph).
Here’s my mwe
import sys from PyQt5 import QtWidgets, QtCore, QtGui import pyqtgraph as pg class RectItem(pg.GraphicsObject): def __init__(self): super().__init__() self.rect = QtCore.QRectF(0, 0, 1, 1) self.picture = QtGui.QPicture() self.generate_picture() def generate_picture(self): painter = QtGui.QPainter(self.picture) painter.setPen(pg.mkPen('r')) painter.drawRect(self.rect) painter.end() def paint(self, painter, option, widget=None): print('paint') painter.drawPicture(0, 0, self.picture) def boundingRect(self): return QtCore.QRectF(self.picture.boundingRect()) def move(self, x, y): print(f'{x} {y}') self.rect.moveCenter(QtCore.QPointF(x, y)) self.generate_picture() class PlotWidget(pg.PlotWidget): mouse_moved = QtCore.pyqtSignal(float, float) def __init__(self): super().__init__() self.sig = pg.SignalProxy( self.scene().sigMouseMoved, rateLimit=60, slot=self._mouse_moved, ) def _mouse_moved(self, event): pos, = event mousePoint = self.plotItem.vb.mapSceneToView(pos) x = mousePoint.x() y = mousePoint.y() self.mouse_moved.emit(x, y) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) main = PlotWidget() rect = RectItem() main.mouse_moved.connect(rect.move) main.addItem(rect) main.show() sys.exit(app.exec_())
Advertisement
Answer
Just redrawing the contents of an internal QPicture doesn’t affect the graphics item in any way, you must call update()
in order to correctly refresh the item. Also consider that since you’re actually changing the bounding rect of the item, you must also call prepareGeometryChange()
before changing the geometry, otherwise you’ll see artifacts due to the previous rectangle position not correctly cleared up.
def move(self, x, y): self.rect.moveCenter(QtCore.QPointF(x, y)) self.prepareGeometryChange() self.generate_picture() self.update()
Also, if you only need a rectangle to move around with the mouse, consider using the simpler QGraphicsRectItem which doesn’t require any painting implementation.