我正在使用 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_())
您可以做的是创建一个空的散点图项并将其添加到
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()])
我自己也在寻找类似的东西,但我需要能够自己调整矩形的大小并提取矩形的坐标。最终我想出了一个基于 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