Writing a script to render arbitrary HTML as an image, and using PyQt. I’m confused as to why my QApplication.exit call isn’t making QApplication.exec_ return. Any ideas on this?
class ScreenshotterApplication(QApplication):
def __init__(self, args, html):
QApplication.__init__(self, args)
self.html = html
self.browser = QWebView()
self.browser.resize(0, 0)
self.browser.loadFinished.connect(self.save)
self.browser.loadProgress.connect(self.progress)
def render(self):
self.browser.setHtml(self.html)
def progress(self, progress):
print '%d%%' % progress
def save(self, finished):
success = False
if finished:
print 'saving...'
# ... snip ...
success = pixmap.save('screenshot.png')
if success:
print 'saved as "screenshot.png"'
QApplication.exit(0 if success else 1)
def exec_(self, *args, **kwargs):
self.render()
super(QApplication, self).exec_(*args, **kwargs)
def take_screenshot(html):
app = ScreenshotterApplication(sys.argv, html)
return app.exec_()
if __name__ == "__main__":
print take_screenshot('<h1 style="width: 500px">Hello, World!</h1>')
QApplication.exittells the application to leave the main event loop, i.e. to return fromexec_()as soon as possible.Your problem is that the small piece of static HTML is so easy to retrieve and render, QtWebKit does it right when setHtml is called. No delays or background processing, everything’s done before setHtml returns. So,
saveis called before the main loop starts (i.e. beforeexec_is called).It’s like writing
returnwhen you’re not in a function – except Qt will just ignoreexitquietly if the loop isn’t running.Solution: Use a
QueuedConnectionin yourconnectcall to force the signal to be queued, and delivered when event loop starts. This’ll also work if the loop is already running, of course.