Question

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?

Was it helpful?

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

OTHER TIPS

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_()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top