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

PySide6 QScrollArea滚动时绘制内容出现残影问题求助

问题解决方法

核心问题原因

滚动时线条残留是因为paintEvent重绘时未清除旧的绘制内容,且滚动过程中仅重绘局部区域,导致之前的线条未被覆盖;同时未正确监听滚动事件触发实时重绘。

具体修复步骤

1. 清除重绘区域背景

在paintEvent开头添加背景填充代码,确保每次重绘时覆盖旧内容:

def paintEvent(self, event):
    painter = QPainter(self)
    painter.setRenderHint(QPainter.Antialiasing)
    # 清除重绘区域背景,避免旧绘制残留
    painter.fillRect(event.rect(), self.palette().window())
    
    if self.scroll_area:
        painter.setPen(QPen(QColor("Red"), 5))
        x_pos = self.scroll_area.horizontalScrollBar().value() + 1
        painter.drawLine(x_pos, 0, x_pos, 500)

    rect = QRectF(800, 0, 100, 100)
    painter.drawRect(rect)

2. 监听滚动条事件触发重绘

在Capacity_Scroll_Area的初始化中,连接滚动条的valueChanged信号到绘图Widget的update()方法,确保滚动时实时触发重绘:

class Capacity_Scroll_Area(QScrollArea):
    def __init__(self):
        super().__init__()

        self.capacity_viewer = Capacity_Drawer()
        self.capacity_viewer.set_scroll_area(self)

        # 连接滚动条信号,滚动时触发重绘
        self.horizontalScrollBar().valueChanged.connect(self.capacity_viewer.update)

        self.setWidget(self.capacity_viewer)
        self.setWidgetResizable(True)

3. 修正重复设置最小尺寸的问题

Capacity_Drawer的__init__中重复调用setMinimumSize,第二个会覆盖第一个,保留符合需求的设置即可:

def __init__(self):
    super().__init__()
    self.scroll_area = None
    # 保留内容的大尺寸最小限制,确保滚动范围足够
    self.setMinimumSize(10000, 10000)

完整修正代码

import sys
from PyQt5.QtWidgets import (QWidget, QScrollArea, QMainWindow, QApplication)
from PyQt5.QtGui import QPainter, QPen, QColor, QRectF

class Capacity_Drawer(QWidget):
    def __init__(self):
        super().__init__()
        self.scroll_area = None
        self.setMinimumSize(10000, 10000)

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        # 清除重绘区域背景
        painter.fillRect(event.rect(), self.palette().window())
        
        if self.scroll_area:
            painter.setPen(QPen(QColor("Red"), 5))
            x_pos = self.scroll_area.horizontalScrollBar().value() + 1
            painter.drawLine(x_pos, 0, x_pos, 500)

        rect = QRectF(800, 0, 100, 100)
        painter.drawRect(rect)

    def set_scroll_area(self, scroll_area: QScrollArea):
        """Set a reference to the parent scroll area."""
        self.scroll_area = scroll_area

class Capacity_Scroll_Area(QScrollArea):
    def __init__(self):
        super().__init__()

        self.capacity_viewer = Capacity_Drawer()
        self.capacity_viewer.set_scroll_area(self)

        # 连接滚动条信号触发实时重绘
        self.horizontalScrollBar().valueChanged.connect(self.capacity_viewer.update)

        self.setWidget(self.capacity_viewer)
        self.setWidgetResizable(True)

class window(QMainWindow):
    def __init__(self):
        super().__init__()
        cap_scroll_area = Capacity_Scroll_Area()
        self.setCentralWidget(cap_scroll_area)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = window()
    window.show()
    sys.exit(app.exec())

额外说明

如果需要让图例完全固定在视口左侧(不随内容滚动而移动),更合理的做法是将图例绘制在QScrollArea的视口上,或者单独创建一个固定在窗口左侧的独立Widget,避免与滚动内容的坐标逻辑混淆。

内容的提问来源于stack exchange,提问作者user23346328

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 08:15:23