如何在 PyQtGraph 图中单击鼠标的位置绘制并填充矩形

问题描述 投票:0回答:2

我正在使用 PyQt5 和 PyQtGraph。我简化了下面的示例代码。然后我想在绘图视图中每次单击鼠标时在鼠标点击的位置绘制一个红色的小矩形,从而在绘图视图中积累几个红色矩形。下面的代码有一个#???评论我需要一些关于绘制红色矩形的代码的帮助。

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_())
python pyqt5 rectangles pyqtgraph
2个回答
2
投票

您可以做的是创建一个空的散点图项并将其添加到

self.qPlotWidget
。然后在
mousrClickedEvent
中,您可以将鼠标位置添加到该散点图项的点列表中,即

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()])

0
投票

我自己也在寻找类似的东西,但我需要能够自己调整矩形的大小并提取矩形的坐标。最终我想出了一个基于 pyqtgraph

PlotWidget
编写一个类,但使用鼠标右键单击来绘制矩形 ROI(而不是缩放)。我在这里分享了它,以防偶然发现该线程的人正在寻找类似的东西

from PyQt6 import QtCore
from PyQt6.QtGui import QMouseEvent, QKeyEvent
import pyqtgraph as pg


class RectROIPlotWidget(pg.PlotWidget):
    """PlotWidget with a rectangular ROI that can be drawn by right-clicking and dragging the mouse"""
    def __init__(self, *args, **kwargs):
        """Initialize method of the RectROIPlotWidget"""
        super().__init__(*args, **kwargs)
        
        # disable autorange by default to avoid unexpected behaviour when drawing ROI
        self.plotItem.vb.autoRange(False)

        # add rectangular ROI
        self.roi_rect = None
        self.reset_roi_rect()

    def reset_roi_rect(self):
        """Reset the rectangular ROI"""
        # remove ROI from plot if it exists
        if self.roi_rect in self.items():
            self.removeItem(self.roi_rect)

        # define start point
        self.start_point = [0, 0]

        # add rectangular ROI
        self.roi_rect = pg.RectROI(
            pos = [-1, -1],
            size = [0, 0],
            rotatable = False,
            invertible = True,
            pen = pg.mkPen([200, 200, 200], width=2, style=QtCore.Qt.PenStyle.DotLine), # modify for desired color
            hoverPen = pg.mkPen([255, 255, 255], width=2, style=QtCore.Qt.PenStyle.DashLine) # modify for desired color
        )
        self.addItem(self.roi_rect)
        self.roi_rect.setZValue(1000)

        # set flag for drawing ROI
        self.draw_flag = False

    def mousePressEvent(self, event: QMouseEvent):
        """Mouse press event handling the start of drawing the ROI
        
        Arguments
        ---------
            - event (QMouseEvent): mouse press event
        """
        if event.button().name == 'RightButton':
            self.reset_roi_rect()
            self.draw_flag = True
            mouse_point = self.plotItem.vb.mapSceneToView(event.scenePosition())
            self.start_point = [mouse_point.x(), mouse_point.y()]
        else:
            super().mousePressEvent(event)

    def mouseMoveEvent(self, event: QMouseEvent):
        """Mouse move event handling the drawing of the ROI
        
        Arguments
        ---------
            - event (QMouseEvent): mouse move event
        """
        if self.draw_flag:            
            mouse_point = self.plotItem.vb.mapSceneToView(event.scenePosition())
            bottom_left = [min(self.start_point[0], mouse_point.x()), min(self.start_point[1], mouse_point.y())]
            top_right = [max(self.start_point[0], mouse_point.x()), max(self.start_point[1], mouse_point.y())]
            self.roi_rect.setPos(bottom_left)
            self.roi_rect.setSize([top_right[0] - bottom_left[0], top_right[1] - bottom_left[1]])

        super().mouseMoveEvent(event)

    def mouseReleaseEvent(self, event: QMouseEvent):
        """Mouse release event handling the end of drawing the ROI
        
        Arguments
        ---------
            - event (QMouseEvent): mouse release event
        """
        if event.button().name == 'RightButton':
            self.draw_flag = False

        super().mouseReleaseEvent(event)

    def keyPressEvent(self, event: QKeyEvent):
        """Key press event handling the removal of the ROI when pressing escape
        
        Arguments
        ---------
            - event (QKeyEvent): key press event
        """
        # remove ROI on pressing escape
        if event.key() == QtCore.Qt.Key.Key_Escape:
            self.roi_rect.setPos([-1, -1])
            self.roi_rect.setSize([0, 0])

        super().keyPressEvent(event)

    def get_roi_rect_coords(self) -> tuple:
        """Get the coordinates of the rectangular ROI
        
        Returns
        -------
            - tuple: tuple with two lists:
                - list: bottom left coordinates of the ROI
                - list: top right coordinates of the ROI
        """
        # get bottom left and size of ROI
        bottom_left = list(self.roi_rect.pos())
        size = list(self.roi_rect.size())

        # determine top right of ROI
        top_right = [bottom_left[0] + size[0], bottom_left[1] + size[1]]

        return bottom_left, top_right

© www.soinside.com 2019 - 2024. All rights reserved.