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

QPrintPreviewWidget显示水平滚动条时致应用冻结的问题求助

PySide2 5.15.2.1中QPrintPreviewWidget水平滚动条触发冻结的解决方案

在Windows 11环境下使用PySide2 5.15.2.1时,QPrintPreviewWidget存在一个Bug:当窗口宽度被调整到使控件的滚动区域显示水平滚动条(且文档已有垂直滚动条)时,应用会立即无响应、冻结,直到再次调整窗口让水平滚动条消失才恢复。

触发该Bug的示例代码:

from PySide2.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayout
from PySide2.QtGui import QTextDocument
from PySide2.QtPrintSupport import QPrinter, QPrintPreviewWidget

app = QApplication()

doc = QTextDocument()
doc.setPlainText('\n' * 200)

printer = QPrinter()
view = QPrintPreviewWidget(printer)
view.paintRequested.connect(doc.print_)

window = QWidget()
layout = QHBoxLayout()
layout.addWidget(view)
layout.addWidget(QLabel('Just to trigger the horizontal scrollbar'))
window.setLayout(layout)
window.show()

app.exec_()

以下是几种有效的解决方案:

  • 防抖处理打印请求
    原代码中直接将paintRequested信号连接到doc.print_,会在滚动条调整过程中频繁触发打印渲染,导致主线程阻塞。添加防抖机制可以避免这种情况:

    from PySide2.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayout
    from PySide2.QtGui import QTextDocument
    from PySide2.QtPrintSupport import QPrinter, QPrintPreviewWidget
    from PySide2.QtCore import QTimer
    
    app = QApplication()
    
    doc = QTextDocument()
    doc.setPlainText('\n' * 200)
    
    printer = QPrinter()
    view = QPrintPreviewWidget(printer)
    
    render_timer = QTimer()
    render_timer.setSingleShot(True)
    render_timer.setInterval(100)
    
    def render_doc(printer):
        doc.print_(printer)
    
    def delayed_render(printer):
        render_timer.timeout.connect(lambda: render_doc(printer))
        render_timer.start()
    
    view.paintRequested.connect(delayed_render)
    
    window = QWidget()
    layout = QHBoxLayout()
    layout.addWidget(view)
    layout.addWidget(QLabel('Just to trigger the horizontal scrollbar'))
    window.setLayout(layout)
    window.show()
    
    app.exec_()
    
  • 禁用水平滚动条
    直接获取QPrintPreviewWidget内部的滚动区域,强制关闭水平滚动条的显示,从根源上避免触发Bug:

    # 在创建view后添加以下代码
    from PySide2.QtWidgets import QScrollArea
    from PySide2.QtCore import Qt
    
    scroll_area = view.findChild(QScrollArea)
    if scroll_area:
        scroll_area.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
    
  • 升级PySide版本
    该Bug大概率是PySide2 5.15.2.1的版本特有问题,后续维护版本(如5.15.7)或PySide6已经修复了这类Windows平台的控件兼容性问题,升级到新版本可以彻底解决。

  • 临时规避:设置最小宽度
    如提问者所说,通过setMinimumWidth设置控件的最小宽度,确保窗口调整不会触发水平滚动条:

    view.setMinimumWidth(800)  # 根据打印内容的实际宽度调整数值
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 12:32:44