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
相关产品推荐
相关产品推荐

