I need some help figuring out how to solve this error. As I described it on SO[1]:
I'm working on a project where I use a modified `QWebView`. I'm getting this error: 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. I have read about [PySide pitfalls](http://qt-project.org/wiki/PySide_Pitfalls) already, and I've been saving that `QtWebKit.QWebFrame` as an attribute of my modified `QWebView` **from the beggining of the project** with the method `setframeafterloadfinished` which is called when the page finishes loading, the problem raised after some majors changes on my modified `QWebView`. Here is the source code showing what I changed: diff -r 916f0091fee8 src/customwebview.py --- a/src/customwebview.py Thu Oct 30 19:54:57 2014 -0600 +++ b/src/customwebview.py Mon Nov 03 20:22:51 2014 -0600 @@ -4,6 +4,7 @@ from PySide.QtWebKit import QWebView from PySide import QtCore, QtGui +from . import webelementinfo class CustomQWebView(QWebView): @@ -12,19 +13,16 @@ """ Init the custom class """ super(CustomQWebView, self).__init__(*args, **kwargs) - self.colors = {0: QtGui.QColor(255, 165, 0), - 1: QtGui.QColor(135, 206, 235), - 2: QtGui.QColor(135, 235, 164), - 3: QtGui.QColor(235, 135, 206), - 4: QtGui.QColor(235, 164, 135)} - self.colorfill = None + 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.lastelement = None - self.lastelementboundingrect = None + self.element = None self.loadFinished.connect(self.setframeafterloadfinished) - self.pen = QtGui.QPen() - self.pen.setWidth(2) - self.drawrects = False + self.selectCommentsArea() @QtCore.Slot() def selectCommentsArea(self): @@ -63,11 +61,15 @@ if self.drawrects: if self.currentframe: hittestresult = self.currentframe.hitTestContent(event.pos()) - element = hittestresult.element() - if self.lastelement != element: - self.lastelement = element - self.lastelementboundingrect = hittestresult.boundingRect() - self.update() + 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): @@ -76,22 +78,8 @@ if self.drawrects: # then the rectangle - if self.lastelementboundingrect: - painter = QtGui.QPainter(self) - painter.setPen(self.defaultpen) - # This rectangles takes into account any offset of the scroll - # bar so the rectangle can be drawn correctly - rect = QtCore.QRect() - rect.setRect(self.lastelementboundingrect.x() - - self.currentframe.scrollPosition().x(), - self.lastelementboundingrect.y() - - self.currentframe.scrollPosition().y(), - self.lastelementboundingrect.width(), - self.lastelementboundingrect.height()) - # painter.drawRect(QtCore.QRectF(self.lastelementcurrectrect)) - painter.drawRect(QtCore.QRectF(rect)) - painter.fillRect( - QtCore.QRectF(rect), self.colorfill) + if self.element: + self.element.update() def setframeafterloadfinished(self): self.currentframe = self.page().mainFrame() @@ -109,15 +97,7 @@ commentary text. """ self.drawrects = True - self.colorfill = self.colors[forarea] - self.colorfill.setAlpha(128) - - colorborder = self.colors[forarea] - self.pen.setColor(colorborder) + self.color = self.colors[forarea] # defines what we are looking to select self.selecttype = forarea and here it is again but complete, **and functional** (just be sure to put the file `webelementinfo.py` in the same directory as this code before running a test): #!/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_() Here is the other file that have the definition of that new class `WebElement` that I write and start to use: #!/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 My project should work right as if I didn't change anything, however, with these changes it doesn't. What am I doing wrong? Am I missing something about `QWebFrame`s? [1]: http://stackoverflow.com/q/26726878/2020214 -- Pax et bonum. Jorge Araya Navarro. ES: DiseƱador Publicitario, Programador Python y colaborador en Parabola GNU/Linux-libre EN: Ads Designer, Python programmer and contributor Parabola GNU/Linux-libre EO: Anonco grafikisto, Pitino programalingvo programisto kai kontribuanto en Parabola GNU/Linux-libre https://es.gravatar.com/shackra _______________________________________________ PySide mailing list PySide@qt-project.org http://lists.qt-project.org/mailman/listinfo/pyside