PyQtGraph中无需clear()更新QGraphicsRectItem的实现方法
解决方案:仅更新矩形位置,避免重绘散点图
当然可以只更新矩形的位置和大小,不需要重新绘制整个散点图。你的问题在于每次拖动滑块时都创建了新的QGraphicsRectItem并添加到绘图部件,导致旧矩形残留。正确的做法是将矩形对象作为类的成员变量,第一次创建后,后续仅更新它的属性,而不是新建。
修改后的完整代码
# ------------------------------------------------------ # ---------------------- main.py ----------------------- # ------------------------------------------------------ from PySide6 import QtWidgets from PySide6.QtWidgets import* from superqt import QDoubleRangeSlider import pyqtgraph as pg import numpy as np class MyWidget(QtWidgets.QWidget): def __init__(self): super().__init__() self.setWindowTitle("pyqtgraph refresh") # 初始化矩形对象为None,作为类属性 self.cond1Rect = None self.QSlider = QDoubleRangeSlider() self.QSlider.setRange(0, 1) self.QSlider.setValue((0.2, 0.8)) self.QSlider2 = QDoubleRangeSlider() self.QSlider2.setRange(0, 1) self.QSlider2.setValue((0.2, 0.8)) self.QSlider.valueChanged.connect(self.update_rect) self.QSlider2.valueChanged.connect(self.update_rect) self.widgetGraph = pg.PlotWidget() self.layout = QtWidgets.QVBoxLayout(self) self.layout.addWidget(self.QSlider) self.layout.addWidget(self.QSlider2) self.layout.addWidget(self.widgetGraph) self.plot_data() self.update_rect() def plot_data(self): CH3 = np.random.rand(500,500) CH2 = np.random.rand(500,500) CH2_1d = CH2.flatten() CH3_1d = CH3.flatten() scatter = pg.ScatterPlotItem(CH2_1d, CH3_1d, size=1, pen=pg.mkPen(None), brush=pg.mkBrush(255, 255, 255, 120)) self.widgetGraph.addItem(scatter) def update_rect(self): CH2Start = self.QSlider.value()[0] CH3Start = self.QSlider2.value()[0] CH2Length = self.QSlider.value()[1]-self.QSlider.value()[0] CH3Length = self.QSlider2.value()[1]-self.QSlider2.value()[0] if self.cond1Rect is None: # 第一次创建矩形并添加到绘图部件 self.cond1Rect = pg.QtWidgets.QGraphicsRectItem(CH2Start, CH3Start, CH2Length, CH3Length) self.cond1Rect.setPen(pg.mkPen('r', width=2)) self.widgetGraph.addItem(self.cond1Rect) else: # 仅更新矩形的位置和大小,无需新建或重绘散点图 self.cond1Rect.setRect(CH2Start, CH3Start, CH2Length, CH3Length) if __name__ == "__main__": app = QtWidgets.QApplication([]) window = MyWidget() window.show() app.exec_()
关键改动说明
- 将
cond1Rect定义为类的成员变量self.cond1Rect,初始化为None - 把原来的
draw_rect方法改名为update_rect,逻辑改为:- 若矩形未创建,则新建并添加到绘图部件
- 若矩形已存在,直接调用
setRect()方法更新其位置和大小,这个操作只会重绘矩形本身,不会影响已绘制的散点图
额外建议:使用PyQtGraph内置的ROI类
如果你需要更灵活的交互(比如直接拖动矩形调整位置/大小),可以使用PyQtGraph的RectROI类,它专门为这类交互式区域选择设计,比手动用QGraphicsRectItem更方便:
# 替换update_rect方法中的矩形创建逻辑 if self.cond1Rect is None: # 创建RectROI,参数为(起始坐标, 大小) self.cond1Rect = pg.RectROI([CH2Start, CH3Start], [CH2Length, CH3Length], pen=pg.mkPen('r', width=2)) self.widgetGraph.addItem(self.cond1Rect) # 可选:监听ROI的变化,同步到滑块 self.cond1Rect.sigRegionChanged.connect(self.sync_roi_to_sliders) else: self.cond1Rect.setPos(CH2Start, CH3Start) self.cond1Rect.setSize([CH2Length, CH3Length]) # 添加同步ROI到滑块的方法 def sync_roi_to_sliders(self): pos = self.cond1Rect.pos() size = self.cond1Rect.size() self.QSlider.setValue((pos.x(), pos.x() + size.x())) self.QSlider2.setValue((pos.y(), pos.y() + size.y()))
这样既可以通过滑块控制矩形,也可以直接拖动矩形来调整,交互性更强。
内容的提问来源于stack exchange,提问作者RamonD
相关产品推荐
相关产品推荐

