Search code examples
pythonpyqt5rectanglespyqtgraph

How to draw and fill a rectangle in a PyQtGraph plot at position where mouse is clicked


I am using PyQt5 and PyQtGraph. I have simplified the example code below. Then I want to draw in the plot view a small red rectangle each time the mouse is clicked at the position where the mouse is clicked, thus accumulating several red rectangles in the plot view. The code below has a #??? comment where I need some help with code that will draw the red rectangle(s).

import sys
from PyQt5 import QtWidgets
import numpy as np
import pyqtgraph as pg
from pyqtgraph import PlotWidget, plot

# *********************************************************************************************
# *********************************************************************************************

class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.setWindowTitle("My MainWindow")
        self.qPlotWidget = pg.PlotWidget(self)
        self.qPlotWidget.setLabel("bottom", "X-Axis")
        self.qPlotWidget.setLabel("left", "Y-Axis")
        self.qPlotWidget.scene().sigMouseClicked.connect(self.mouseClickedEvent)

        data1 = np.zeros((2, 2), float) # create the array to hold the data
        data1[0] = np.array((1.0, 10.0))
        data1[1] = np.array((2.0, 20.0))

        pen1 = pg.mkPen(color=(255,0,0), width=1) # red
        self.qPlotWidget.plot(data1, pen=pen1, name="data1")

    def mouseClickedEvent(self, event):
        print("mouseClickedEvent")
        pos = event.scenePos()
        if (self.qPlotWidget.sceneBoundingRect().contains(pos)):
            mousePoint = self.qPlotWidget.plotItem.vb.mapSceneToView(pos)
            print("mousePoint=", mousePoint)

            # draw and fill a 2-pixel by 2-pixel red rectangle where
            # the mouse was clicked at [mousePoint.x(), mousePoint.y()]
            # ??? add code here

    def resizeEvent(self, event):
        size = self.geometry()
        self.qPlotWidget.setGeometry(10, 10, size.width()-20, size.height()-20)

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    w = MainWindow()
    screen = QtWidgets.QDesktopWidget().screenGeometry()
    w.setGeometry(100, 100, screen.width()-200, screen.height()-200) # x, y, Width, Height
    w.show()

    sys.exit(app.exec_())

Solution

  • What you could do is to create an empty scatter plot item and add it to self.qPlotWidget. Then in mousrClickedEvent you could add the mouse position to the list of points of this scatter plot item, i.e.

    class MainWindow(QtWidgets.QMainWindow):
        def __init__(self, parent=None):
            .... as before ....
    
            # add empty scatter plot item with a red brush and a square as the symbol to plot widget
            brush = pg.mkBrush(color=(255,0,0))
            self.scatterItem = pg.ScatterPlotItem(pen=None, size=10, brush=brush, symbol='s')
            self.qPlotWidget.addItem(self.scatterItem)
    
    
        def mouseClickedEvent(self, event):
            pos = event.scenePos()
            if (self.qPlotWidget.sceneBoundingRect().contains(pos)):
                mousePoint = self.qPlotWidget.plotItem.vb.mapSceneToView(pos)
    
                # add point to scatter item
                self.scatterItem.addPoints([mousePoint.x()], [mousePoint.y()])