PyQt:QImage() 返回一个 'Null'-Image [英] PyQt: QImage() returns a 'Null'-Image

查看:99
本文介绍了PyQt:QImage() 返回一个 'Null'-Image的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要为我的一个项目截取网站的屏幕截图.作为开发语言,我使用 Python 并使用 PyQt 的 Webkit 截取屏幕截图.下面的脚本是用于捕获网站的代码(它被部分修改,但大部分仍然与 webscraping.com).

I need to take screenshots of websites for a project of mine. As development language I use Python and to take the Screenshots I use Webkit from PyQt. The script below is the code used to take capture the websites (it's partially modified but most of it is still equal to the original from webscraping.com).

现在我的问题如下:
大多数情况下它都可以正常工作,但是,有时会发生以下异常.

Now my problem is the following:
Most of the time it works without any problems, but, from time to time it happens that the following exception.

QPainter::begin: Paint device returned engine == 0, type: QPainter::setRenderHint: Painter must be active to set rendering hints
QPainter::setBrush: Painter not active
QPainter::pen: Painter not active
QPainter::setPen: Painter not active
QPainter::end: Painter not active, aborted

我已经找到了创建图像的问题

I've already tracked down the problem to the creation of the image

image = QImage(self.page().viewportSize(), QImage.Format_ARGB32) 

此行返回的 QImage 有时为 Null - 我使用 QImage 的 .isNull() 方法检查了这一点.
根据 Qt 文档,如果没有足够的内存来分配新的 QImage,就会发生这种情况,但我仍然有足够的可用内存.
这种行为在 Windows 和 linux 上运行时发生,所以我认为它不应该依赖于一些依赖于操作系统的东西.我是 Qt 和 PyQt 的新手,所以我希望有人能帮助我.

The QImage returned by this line is sometime Null - I checked this using the .isNull()-method of QImage.
According to the Qt documentation this happens if there isn't enough memory to allocate a new QImage, but I still have way enough free memory.
This beahaviour occured while running on windows and also on linux, so it should not depend on some os depending stuff, I think. I'm new to Qt and PyQt, so I hope someone can help me.

from PyQt4.QtCore import *
from PyQt4.QtGui import *
from PyQt4.QtWebKit import *
import sys
import time

# ############################################################# #
# This script is based on the following script:                 #
# https://webscraping.com/blog/Webpage-screenshots-with-webkit/ #
# ############################################################# #

class Screenshot(QWebView):
    _instance = None

    @staticmethod
    def get_instance():
        # TODO: Add a lock around the if including the creation!
        if Screenshot._instance is None:
            Screenshot._instance = Screenshot()

        return Screenshot._instance

    def __init__(self):
        self.app = QApplication(sys.argv)
        QWebView.__init__(self)
        self._loaded = False
        self.loadFinished.connect(self._loadFinished)

    def capture(self, url, output_file):
        self.load(QUrl(url))
        self.wait_load()
        # set to webpage size
        frame = self.page().mainFrame()
        self.page().setViewportSize(frame.contentsSize())
        # render image
        # creating the image. Here it happens that QImage returns a 'Null'-Image
        image = QImage(self.page().viewportSize(), QImage.Format_ARGB32)
        # check if there's no image allocated
        if image.isNull(): 
            print 'image.isNull() is True'
        if image is None:
            print 'image is None is True'
        painter = QPainter(image)
        frame.render(painter)
        painter.end()
        print 'saving', output_file
        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

if __name__ == '__main__':
    # a simple way to get the exceptions is to try to create multiple screenshots
    sc = Screenshot()
    for i in range(0, 25):
        sc.capture('http://google.de', str(i) + '.png')

    for i in range(25, 50):
        sc.capture('http://de.wikipedia.org', str(i) + '.png')

推荐答案

好的.我已经更深入地跟踪了这个问题.似乎在读取 QWebPages mainFrame 的 contentsSize 以创建 QImage 时,它​​有时是 (0, 0).

Ok. I've tracked the problem a bit further down. It seems like the contentsSize of the QWebPages mainFrame is sometimes (0, 0) when it is read to create the QImage.

frame = self.page().mainFrame()
self.page().setViewportSize(frame.contentsSize()) # frame.contentsSize() = (0, 0)
image = QImage(self.page().viewportSize(), QImage.Format_ARGB32) # so we're creating here an Image with Width: 0 and Height: 0

所以基本上 QImage 似乎是 Null,因为它创建的大小是 (0, 0).
这个问题可以通过检查 mainFrames contentsSize 是否为 (0, 0) 来解决.如果它是 (0, 0),则需要处理 QApplication 上的未完成事件,直到设置新的 contentsSize 为止.我现在正在使用以下代码段执行此操作:

So basically the QImage seems to be Null, because the size it's created with is (0, 0).
This problem can be solved by checking wether the mainFrames contentsSize is (0, 0) or not. If it is (0, 0) it's needed to process outstanding events on the QApplication until the new contentsSize is set. I'm doing this now with the following piece of code:

if frame.contentsSize().width() == 0 or frame.contentsSize().height() == 0:
    print 'ContentsSize = (w: {}, h: {})'.format(frame.contentsSize().width(), frame.contentsSize().height())
    count = 0 # used so we're not starting an infinite loop
    while (frame.contentsSize().width() == 0 or frame.contentsSize().height() == 0) and count < 5:
        count += 1
        self.app.processEvents()
        time.sleep(1)

这篇关于PyQt:QImage() 返回一个 'Null'-Image的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆