Search code examples
pythonpdfqt4popplerpixmap

What is the most efficient way to display multiple pixmaps into a scroll area?


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?


Solution

  • 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)