I'm trying to save a screenshot of a website with QtWebEngineView, but the resulting image always ends up being empty.
import sys
import time
from PyQt6.QtCore import *
from PyQt6.QtGui import *
from PyQt6.QtWidgets import QApplication, QWidget
from PyQt6.QtWebEngineWidgets import QWebEngineView
class Screenshot(QWebEngineView):
def __init__(self):
self.app = QApplication(sys.argv)
QWebEngineView.__init__(self)
self._loaded = False
self.loadFinished.connect(self._loadFinished)
def capture(self, url, output_file):
self.resize(QSize(1024, 768))
self.load(QUrl(url))
self.wait_load()
image = QImage(self.size(), QImage.Format.Format_ARGB32)
painter = QPainter(image)
self.render(painter)
painter.end()
image.save(output_file)
def wait_load(self, delay=0):
# process app events until page loaded
while not self._loaded:
self.app.processEvents()
time.sleep(delay)
self._loaded = False
def _loadFinished(self, result):
self._loaded = True
s = Screenshot()
s.capture("https://www.google.com", "screenshot.png")
I've tried variations of the code where the QTWebEngineView is rendered in an application window and that part works. The wait_load
also ensures the website is loaded before proceeding to paint. Yet somehow the rendered image is always a full white png instead of the website.
Edit: Voting to reopen because the solution in the "duplicate" does not seem to resolve this case.
The problem is caused by the QWebengineView not being rendered because the show() method is not called. As indicated in the other posts you should also use Qt.WidgetAttribute.WA_DontShowOnScreen
. Here is a version that avoids using time.sleep
and QXApplication.processEvents
.
import sys
from PyQt6.QtCore import Qt, QEventLoop, QSize, QUrl
from PyQt6.QtGui import QImage, QPainter
from PyQt6.QtWidgets import QApplication
from PyQt6.QtWebEngineWidgets import QWebEngineView
class Screenshot(QWebEngineView):
def __init__(self):
self.app = QApplication(sys.argv)
QWebEngineView.__init__(self)
self.setAttribute(Qt.WidgetAttribute.WA_DontShowOnScreen)
self.show()
self._output_file = ""
self._loop = QEventLoop()
self.loadFinished.connect(self._loop.quit)
def capture(self, url, output_file):
self._output_file = output_file
self.resize(QSize(1024, 768))
self.load(QUrl(url))
self.wait_load()
def wait_load(self):
self._loop.exec()
image = QImage(self.size(), QImage.Format.Format_ARGB32)
painter = QPainter(image)
self.render(painter)
painter.end()
image.save(self._output_file)
s = Screenshot()
for i in range(10):
s.capture("https://www.google.com", f"screenshot{i}.png")