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

QPdfView滚动时Overlay位置调整及视口渲染像素获取求助

问题解决与代码修正

你的核心问题在于手动计算滚动偏移和页面缩放的逻辑不准确,QPdfView本身提供了pageViewport()方法可以直接获取页面在视口中的位置与尺寸,无需自己估算滚动量。下面是修正后的代码,同时实现了你需要的可见像素高度计算:

from PySide6.QtCore import QRectF
from PySide6.QtGui import QPainter, QColor
from PySide6.QtPdfWidgets import QPdfView
from PySide6.QtCore import Qt
from PySide6.QtPdf import QPdfDocument

class CustomPdfView(QPdfView):  
    def __init__(self, parent=None):
        super().__init__(parent)
        
        # 测试用的高亮区域,键为页码(从0开始)
        self.highlights: dict[int, list[QRectF]] = {
            i : [QRectF(150.0, 150.0, 300.0, 300.0)] for i in range(200)
            }

    def paintEvent(self, event):
        super().paintEvent(event)

        doc = self.document()
        if doc.status() != QPdfDocument.Status.Ready:
            return

        current_page = self.pageNavigator().currentPage()
        if current_page not in self.highlights:
            return

        painter = QPainter(self.viewport())
        painter.setRenderHint(QPainter.RenderHint.Antialiasing)
        painter.setBrush(QColor(255, 255, 0, 100))
        painter.setPen(Qt.PenStyle.NoPen)

        # 获取当前页面在视口中的实际显示矩形(包含位置与缩放后的尺寸)
        page_viewport = self.pageViewport(current_page)
        # 获取PDF页面的原始尺寸(单位:点,1点=1/72英寸)
        page_size = doc.pagePointSize(current_page)

        # 计算缩放比例:视口中的页面宽度 / 原始页面宽度
        scale = page_viewport.width() / page_size.width()

        # 计算当前页面的可见像素高度与h_diff
        # page_viewport.height() 就是页面在视口中显示的像素高度
        page_pixel_height = page_size.height() * scale  # 页面完整显示时的像素高度
        visible_pixel_height = page_viewport.height()
        h_diff = page_pixel_height - visible_pixel_height

        for rect in self.highlights[current_page]:
            # 将PDF中的矩形坐标转换为视口坐标
            scaled_rect = QRectF(
                page_viewport.x() + rect.x() * scale,
                page_viewport.y() + rect.y() * scale,
                rect.width() * scale,
                rect.height() * scale
            )
            painter.drawRect(scaled_rect)

        painter.end()

关键修正点说明

  • 使用pageViewport()获取页面位置:这个方法直接返回当前页面在视口中的QRect,包含了页面的左上角坐标(相对于视口)和缩放后的宽高,完全替代了手动计算滚动偏移的逻辑,滚动时位置会自动同步。
  • 正确的坐标转换:PDF页面的坐标是基于原始尺寸的,乘以缩放比例后加上页面视口的偏移量,就能得到准确的视口坐标。
  • 可见像素高度计算:page_viewport.height()是当前页面在视口中实际显示的像素高度,页面完整像素高度是原始高度乘以缩放比例,两者的差值就是你需要的h_diff。

额外提示

  • 如果需要处理多页同时显示的情况(比如连续滚动模式下多个页面在视口中),可以遍历所有可见页面,对每个页面调用pageViewport()来绘制对应的Overlay。
  • 避免在paintEvent中做过多计算,必要时可以缓存缩放比例和页面视口信息,提升性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 23:39:59