You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 02:13:15