Hi Jorge, Would you care to send a shorter version of the code (with the bug, that is) ? It'd help us to reproduce it (and it'd help you to better understand it)
Stefan On Wed, 05 Nov 2014 23:04:41 -0600 Jorge Araya Navarro <[email protected]> wrote: > > 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 > [email protected] > http://lists.qt-project.org/mailman/listinfo/pyside -- Timeo Danaos et dona ferentes Twitter : @Arakowa1 _______________________________________________ PySide mailing list [email protected] http://lists.qt-project.org/mailman/listinfo/pyside
