【问题标题】:How to prevent zooming in QScrollArea from being so rickety-flickery?如何防止 QScrollArea 的缩放变得如此摇摇晃晃?
【发布时间】:2012-05-23 07:09:08
【问题描述】:

我正在使用 PyQt4 和 python-popplerqt4 开发 PDF 阅读器。 PDF 页面(QPixmaps)显示在 QLables 中,在 QFrame 中垂直布局。 QFrame 被放置在 QScrollArea 中。

QMainWindow
   |_ QScrollArea
        |_ QFrame (Document: stretch)
            |_ QLabel (Page: fixed size)
            |   |_ QPixmap (stretch)
            |_ QLabel
            |   |_ QPixmap
            |_ etc.

文档的大小由 QLabels 的固定大小决定。 QPixmap 被设置为相应地拉伸,页面周围的 QFrame 自然地调整其大小。

当我要求缩放时,页面(QLabels)会用QLabel.setFixedSize() 一张一张地调整大小。然而效果是令人失望:调整文档大小看起来摇摇晃晃。相比之下,放大 Evince 或 Mendeley 真的很流畅。

我在其他地方读到过在缩放之前调用 QFrame.hide() 和在缩放之后调用 QFrame.show() 会有所帮助。事实上,它适用于一个小文件。但是,例如,应用于大约 700 页的 PDF 意味着 空白 QScrollArea 超过一秒钟。不好。

如何在 QScrollArea 中缩放文档并产生平滑的缩放效果?

PS: Poppler.Pages 的图像仅为可见的 QLabel 收件人绘制。即调整 700 页文档的大小并不涉及调整那么多图像的大小。实际上,它最多会调整 2 到 4 个图像的大小(并且分辨率越多,分辨率越小)。然后调整 Document 对象的大小仅包括调整 QLabels 的大小,大部分是空的。

【问题讨论】:

  • 我删除了应用动画的部分。它无法工作,因为我的示例需要 QLabels 上的 setFixedSize(),这与通过动画更改大小值相冲突。

标签: python qt4 zooming pyqt4 qscrollarea


【解决方案1】:

经过一些调查和来自 QtForums 的一些帮助,看来 没有简单的解决方案可以使用 QScrollArea 实现所需的缩放效果。否则请证明我错了。

一个更好的工具是QGraphicsView,虽然不太容易实现。它有一个QGraphicsView.scale(float, float) 方法可以完美地缩放!它也更容易使用,因为这种缩放方法甚至不需要维护内容(如果你不从一开始就加载高分辨率,可能除了图像的分辨率)。

QGraphicsScene 然而,QGraphicsView 的内容有点懒惰,需要更多的工作来设置,尤其是在布局方面。就我而言,由于我正在使用 PDF 查看器,因此我需要垂直对齐的图像,QGraphicsLinearLayout 可以做到这一点。

为了后代,这里有一个示例代码,展示了如何将像素图实现到布局中,将场景实现到视图中。当然,它还显示了如何缩放内容。

#!/usr/bin/env python

import sys
from PyQt4 import QtGui, QtCore
from popplerqt4 import Poppler

class Application(QtGui.QApplication):

    def __init__(self):
        QtGui.QApplication.__init__(self, sys.argv)

        scene = QtGui.QGraphicsScene()
        scene.setBackgroundBrush(QtGui.QColor('darkGray'))
        layout = QtGui.QGraphicsLinearLayout(QtCore.Qt.Vertical)
        document = Poppler.Document.load('/home/test.pdf')
        document.setRenderHint(Poppler.Document.Antialiasing)
        document.setRenderHint(Poppler.Document.TextAntialiasing)
        for number in range(document.numPages()):
            page = document.page(number)
            image = page.renderToImage(100, 100)
            pixmap = QtGui.QPixmap.fromImage(image)
            container = QtGui.QLabel()
            container.setFixedSize(page.pageSize())
            container.setStyleSheet("Page { background-color : white}")
            container.setContentsMargins(0, 0, 0, 0)
            container.setScaledContents(True)
            container.setPixmap(pixmap)
            label = scene.addWidget(container)
            layout.addItem(label)

        graphicsWidget = QtGui.QGraphicsWidget()
        graphicsWidget.setLayout(layout)
        scene.addItem(graphicsWidget)
        self.view = View(scene)
        self.view.show()


class View(QtGui.QGraphicsView):

    def __init__(self, parent = None):
        QtGui.QGraphicsView.__init__(self, parent)

    def wheelEvent(self, event):

        if event.delta() > 0:
            self.scale(1.1, 1.1)
        else:
            self.scale(0.9, 0.9)

if __name__ == "__main__":
        application = Application()
        sys.exit(application.exec_())

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-24
    • 1970-01-01
    相关资源
    最近更新 更多