I am trying to make an application that displays a PDF file, using PyQt4 and python-poppler-qt4.

So far I have managed to display the entire document by loading pixmaps generated with Poppler, set on a QLabel and appended to a QFrame. The QFrame is displayed in a QScrollArea.

It looks pretty good, until implementing zooming, which is done by regenerating the pixmaps all over again, with an incremented resolution. This process requires the entire document to be rendered into pixmaps, which obviously takes time and results into an unwanted lag.

Logic wants that I should display images of the pages I am seeing only (it sounds like quantum physics). I have two options in mind:

  1. create blank pages with QLabels and load the image onto them when they become visible in the scroll area;
  2. create only one page and add or remove precedent or subsequent pages right before it should be displayed.

I am not sure I am on the right track or whether there is an alternative.

The first option seems more feasible, because the visibility of a blank page determines when the pixmap has to be uploaded (although I have no idea how to delete that pixmap when the page is hidden). Yet I am not sure that zooming will be faster this way, since a document of, say, 600 pages, will have to be regenerated, albeit with blank pages.

The second option should definitely improve zooming since 1 to 4 pages at a time would have to be regenerated when zooming. In that second case however, I am not sure how to trigger the construction of pages.

What would you suggest?

有帮助吗?

解决方案 2

I've worked out an answer, using option 1 in the question:

def moveEvent(self, event):
    self.checkVisibility()
    event.ignore()

def resizeEvent(self, event):
    self.checkVisibility()
    event.ignore()

def checkVisibility(self):
    print "Checking visibility"
    for page in self.getPages():
        if not page.visibleRegion().isEmpty():
            if page.was_visible:
                pass
            else:
                print page.page_number, "became visible"
                page.was_visible = True
                self.applyImageToPage(page)
        else:
            if page.was_visible:
                print page.page_number, "became invisible"
                page.was_visible = False
            else:
                pass
def applyImageToPage(self, page):
    print "applying image to page", page.page_number
    source = self.getSourcePage(self.getPageNumber(page))
    scale = self.display.scale
        # this is where the error occurs
    image = source.renderToImage(72 * scale, 72 * scale)
    pixmap = QtGui.QPixmap.fromImage(image)
    page.setPixmap(pixmap)

其他提示

wouldn't it be simple to forget the QLabels and directly draw the image:

from PyQt4.QtGui import *
import sys

app = QApplication(sys.argv)

class Test(QWidget):

    def __init__(self):
        super(Test, self).__init__()
        self.painter = QPainter()
        # placeholder for the real stuff to draw
        self.image = QImage("/tmp/test.jpg")

    def paintEvent(self, evt):
        rect = evt.rect()
        evt.accept()
        print rect
        self.painter.begin(self)
        zoomedImage = self.image   # ... calculate this for your images
        sourceRect = rect          # ... caluclate this ...
        # draw it directly
        self.painter.drawImage(rect, self.image, sourceRect)
        self.painter.end()


t = Test()
t.setGeometry(0,0,600,800)

s = QScrollArea()
s.setWidget(t)

s.setGeometry(0,0,300,400)
s.show()
app.exec_()
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top