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

PySide6结合PyMuPDF显示PDF时窗口缩放出现剪切失真问题

PySide结合PyMuPDF查看PDF窗口缩放时剪切失真的解决方法

问题描述

使用PySide6结合PyMuPDF开发PDF查看器时,调整窗口大小会出现PDF内容剪切、失真的问题。

问题原因

  1. 直接将resizeEvent赋值给render_page,未调用父类的resizeEvent方法,导致窗口布局逻辑异常。
  2. 计算缩放比例时使用主窗口尺寸,而非滚动区域的视口可用空间,渲染的PDF尺寸与显示区域不匹配。
  3. 滚动区域开启WidgetResizable=True后,标签控件尺寸随滚动区域变化,进一步干扰渲染尺寸计算。

修复后的代码

import sys
import fitz

from PySide6.QtWidgets import QApplication, QLabel, QMainWindow, QScrollArea
from PySide6.QtGui import QPixmap, QImage
from PySide6.QtCore import Qt

class PDFWindow(QMainWindow):
    def __init__(self, filename):
        super().__init__()
        
        # 打开PDF并获取第一页
        self.pdf_doc = fitz.open(filename)
        self.page = self.pdf_doc[0]

        # 创建用于显示PDF页面的QLabel
        self.label = QLabel()
        self.label.setAlignment(Qt.AlignCenter)
        # 禁止标签自动调整大小,避免干扰渲染尺寸
        self.label.setSizePolicy(Qt.Ignored, Qt.Ignored)

        # 创建滚动区域
        self.scroll_area = QScrollArea()
        self.scroll_area.setWidget(self.label)
        # 关闭WidgetResizable,手动控制标签尺寸
        self.scroll_area.setWidgetResizable(False)
        self.setCentralWidget(self.scroll_area)

        # 初始渲染页面
        self.render_page()

    def resizeEvent(self, event):
        # 调用父类的resizeEvent确保窗口正常布局
        super().resizeEvent(event)
        self.render_page()

    def render_page(self):
        # 获取滚动区域视口的可用尺寸
        viewport_size = self.scroll_area.viewport().size()
        page_rect = self.page.rect()
        page_width = page_rect.width
        page_height = page_rect.height

        # 计算保持宽高比的缩放比例
        zoom_width = viewport_size.width() / page_width
        zoom_height = viewport_size.height() / page_height
        zoom = min(zoom_width, zoom_height)

        # 确保缩放比例不小于0.1,避免过小
        zoom = max(zoom, 0.1)

        # 渲染PDF页面为Pixmap
        pixmap = self.page.get_pixmap(matrix=fitz.Matrix(zoom, zoom), colorspace='rgb')
        image = QImage(pixmap.samples, pixmap.width, pixmap.height, QImage.Format_RGB888)
        cur_pixmap = QPixmap.fromImage(image)
        
        # 更新标签的Pixmap和尺寸
        self.label.setPixmap(cur_pixmap)
        self.label.resize(cur_pixmap.size())

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

关键修改点

  • 重写resizeEvent:不再直接赋值,而是重写方法并调用父类实现,保证窗口布局逻辑正常执行。
  • 使用视口尺寸计算缩放:用滚动区域的viewport().size()替代主窗口大小,确保基于实际显示区域计算缩放比例。
  • 关闭WidgetResizable:手动控制标签的尺寸,避免滚动区域自动调整标签大小导致的渲染偏差。
  • 保持宽高比:通过取宽高缩放比例的最小值,确保PDF页面完整显示且不变形。
  • 设置标签尺寸策略:将标签的尺寸策略设为Ignored,避免Qt自动调整标签大小影响渲染结果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 11:01:27