错误:内部C ++对象(PySide.QtWebKit.QWebFrame)已被删除;但我将其保存为属性以避免这个问题

时间:2014-11-04 02:42:14

标签: python pyside qwebview qwebkit qwebpage

我正在开发一个使用修改后的QWebView的项目。我收到了这个错误:

Traceback (most recent call last):
  File "/home/jorge/coders/universal-scraper/src/customwebview.py", line 63, in mouseMoveEvent            
    hittestresult = self.currentframe.hitTestContent(event.pos())
RuntimeError: Internal C++ object (PySide.QtWebKit.QWebFrame) already deleted.

我已经阅读了PySide pitfalls已经,并且我一直将QtWebKit.QWebFrame个对象保存为修改后的QWebView的属性,方法为{{当页面完成加载时调用1}},在我修改的setframeafterloadfinished上发生的一些主要修改之后引发的问题发生了,在此之前,一切都很顺利。

功能和最小化示例就在这里(只需确保在运行测试之前将文件QWebView放在与此代码相同的目录中):

webelementinfo.py

这是另一个文件,其中包含我编写并开始使用的新类#!/usr/bin/env python2 # coding: utf-8 # VENI, SANCTE SPIRITUS from PySide.QtWebKit import QWebView from PySide import QtCore, QtGui try: from . import webelementinfo except ValueError: import webelementinfo class CustomQWebView(QWebView): def __init__(self, *args, **kwargs): """ Init the custom class """ super(CustomQWebView, self).__init__(*args, **kwargs) self.colors = {0: QtGui.QColor(255, 165, 0, 127), 1: QtGui.QColor(135, 206, 235, 127), 2: QtGui.QColor(135, 235, 164, 127), 3: QtGui.QColor(235, 135, 206, 127), 4: QtGui.QColor(235, 164, 135, 127)} self.color = None self.currentframe = None self.element = None self.loadFinished.connect(self.setframeafterloadfinished) self.selectCommentsArea() @QtCore.Slot() def selectCommentsArea(self): """ For selecting the comment area """ self.setup_rectcolor_area(0) @QtCore.Slot(QtGui.QMouseEvent) def mouseMoveEvent(self, event): super(CustomQWebView, self).mouseMoveEvent(event) if self.drawrects: if self.currentframe: hittestresult = self.currentframe.hitTestContent(event.pos()) element = webelementinfo.WebElement( hittestresult, self.color, self) if not self.element: self.element = element elif self.element != element: self.element = element # FIXME: self.update should draw rects from WebElements too. self.update() @QtCore.Slot(QtGui.QPaintEvent) def paintEvent(self, event): # draw the content first super(CustomQWebView, self).paintEvent(event) if self.drawrects: # then the rectangle if self.element: self.element.update() def setframeafterloadfinished(self): self.currentframe = self.page().mainFrame() def setup_rectcolor_area(self, forarea): """Called when we want to select certain area of a web site This method set-up the painter to a giving color so web elements are drawn with a rect on top. Also activates the flag to allow painting inside CustomQWebView. :param int forarea: For which area we are going to set the painter\\ valid values are: 0 for Comments area, 1 for comment box, 2 for\\ commentator's user name, 3 for comment date and time, 4 for\\ commentary text. """ self.drawrects = True self.color = self.colors[forarea] # defines what we are looking to select self.selecttype = forarea if __name__ == "__main__": app = QtGui.QApplication([]) mainwn = QtGui.QMainWindow() mainwn.resize(800, 696) centralwidget = QtGui.QWidget(mainwn) centralwidget.resize(800, 600) gridlayout = QtGui.QGridLayout(centralwidget) web = CustomQWebView(parent=centralwidget) gridlayout.addWidget(web, 0, 0, 1) web.setUrl(QtCore.QUrl("http://duckduckgo.com")) mainwn.show() app.exec_() 的定义:

WebElement

我的项目应该正常工作,好像我没有改变任何东西,然而,这些改变并没有。我究竟做错了什么?我错过了关于#!/usr/bin/env python2 # coding: utf-8 # VENI, SANCTE SPIRITUS from PySide.QtWebKit import QWebElement, QWebHitTestResult from PySide import QtGui from PySide import QtCore class WebElement(QtCore.QObject): """ Holds information of webelements """ def __eq__(self, other): if isinstance(other, WebElement): return (self.web_element == other.web_element and self.getrect() == other.getrect()) else: raise ValueError("Not same objects") def __ne__(self, other): if isinstance(other, WebElement): return (self.web_element != other.web_element and self.getrect() != other.getrect()) else: raise ValueError("Not same objects") def __init__(self, hittestresult, color, parent=None): super(WebElement, self).__init__(parent) if (not isinstance(hittestresult, QWebHitTestResult) and not isinstance(hittestresult, QWebElement)): raise ValueError( "Argument passed for 'hittestresult' is not" " QtWebkit.QWenHitTestResult or QtWebkit.QWebElement instance" ) if not isinstance(color, QtGui.QColor): raise ValueError( "Argument passed for 'color' is not QtGui.QColor instance" ) try: self.frame = hittestresult.frame() except AttributeError: self.frame = hittestresult.webFrame() self.frame_scroll_x = self.frame.scrollPosition().x() self.frame_scroll_y = self.frame.scrollPosition().y() try: rect = hittestresult.boundingRect() except AttributeError: rect = hittestresult.geometry() self.element_rect_x = rect.x() self.element_rect_y = rect.y() self.element_rect_w = rect.width() self.element_rect_h = rect.height() try: self.web_element = hittestresult.element() except AttributeError: self.web_element = hittestresult self.color = color self.color_darker = color.darker() self.color_darker.setAlpha(255) self.pen = QtGui.QPen(self.color_darker) self.pen.setWidth(2) #self.painter = QtGui.QPainter(self.parent) self.painter = QtGui.QPainter() self.painter.setPen(self.pen) def update(self): """ draw the rect for this element in the CustomQWebView """ rect = self.getrect() rectf = QtCore.QRectF(rect) self.painter.fillRect(rectf, self.color) self.painter.drawRect(rectf) def getrect(self): """ Return the rect for this WebElement """ self.frame_scroll_x = self.frame.scrollPosition().x() self.frame_scroll_y = self.frame.scrollPosition().y() rect = QtCore.QRect() rect.setRect(self.element_rect_x - self.frame_scroll_x, self.element_rect_y - self.frame_scroll_y, self.element_rect_w, self.element_rect_h) return rect s的内容吗?

1 个答案:

答案 0 :(得分:1)

首先,您的示例不是 minimal :文件" webelementinfo.py"是无关紧要的(以及您的课程的许多其他部分),导致问题的是QWebHitTestResult.frame()方法。足以发生错误的代码如下:

@QtCore.Slot(QtGui.QMouseEvent)
def mouseMoveEvent(self, event):
    if self.currentframe:
        hittestresult = self.currentframe.hitTestContent(event.pos())
        hittestresult.frame() # <- will cause the crash on next mouseMoveEvent

ekhumoro所述,这看起来像PySide中的一个与对象所有权相关的错误。您需要避免调用frame()方法 - 它似乎在您的代码中并不是必不可少的。将WebElement的构造函数更改为:

def __init__(self, frame, hittestresult, color, parent=None):

然后:

#try:
#    self.frame = hittestresult.frame()     <-- DO NOT CALL THIS
#except AttributeError:
#    self.frame = hittestresult.webFrame()

self.frame = frame

明确传递框架:

hittestresult = self.currentframe.hitTestContent(event.pos())

element = webelementinfo.WebElement(
    self.currentframe, 
    hittestresult,
    self.color,
    self)

通过这些修复,&#34;内部C ++对象(PySide.QtWebKit.QWebFrame)已被删除。&#34;错误不会发生。