[PyQt] Subclass of QGraphicsObject does not have the correct class name listed in QGraphicsScene.items()

Phil Thompson phil at riverbankcomputing.com
Wed Dec 7 12:56:03 GMT 2011


On Mon, 5 Dec 2011 18:01:25 -0500, Luke Campagnola
<lcampagn at email.unc.edu>
wrote:
> How about this:
> 
> from PyQt4 import QtCore, QtGui
> import sip
> class GObject(QtGui.QGraphicsObject):
>     def boundingRect(self):
>         return QtCore.QRectF(0, 0, 10, 10)
>     def paint(self, p, *args):
>         p.drawRect(self.boundingRect())
> 
> app = QtGui.QApplication([])
> scene = QtGui.QGraphicsScene()
> obj = GObject()
> scene.addItem(obj)
> items = scene.items(QtCore.QPointF(0,0))
> objAddr = sip.unwrapinstance(sip.cast(obj, QtGui.QGraphicsItem))
> itemAddr = sip.unwrapinstance(sip.cast(items[0], QtGui.QGraphicsItem))
> print "Adresses match:", objAddr == itemAddr
> print "QGraphicsObject matches:", obj is items[0]


That turned out to be easier than I thought - thanks for making me look at
it in a different way.

Try current SIP hg or tonight's snapshot.

Phil


> On Mon, Dec 5, 2011 at 16:33, Phil Thompson
<phil at riverbankcomputing.com>
> wrote:
>> On Mon, 5 Dec 2011 12:24:57 -0500, Luke Campagnola
>> <lcampagn at email.unc.edu>
>> wrote:
>>> Howdy Phil,
>>> I'm running into this issue where QGraphicsScene.items() does not
>>> return the correct python objects if the items are subclassed from
>>> QGraphicsObject. Your response to this issue several months ago was:
>>>
>>> On Fri, May 20, 2011 at 11:46, Phil Thompson
>>> <phil at riverbankcomputing.com> wrote:
>>>> It's because QGraphicsObject inherits both QObject and QGraphicsItem.
>>>> items() returns a list of QGraphicsItems which, for a
QGraphicsObject,
>>>> has
>>>> a different C++ address than the original QGraphicsObject. PyQt
doesn't
>>>> recognise that the QGraphicsItem is a cast of the QGraphicsObject. I
>>>> don't
>>>> think there is anything I can (sensibly) do about this.
>>>
>>> The workaround I am using for this bug is to maintain a dictionary
>>> that maps from the QtGui::QGraphicsItem memory address back to the
>>> original python object. Looks something like:
>>>     cache[ sip.unwrapinstance(sip.cast(item, QtGui.QGraphicsItem)) ] =
>> item
>>>
>>> This works, but it's rather messy since every instance of
>>> QGraphicsObject and QGraphicsWidget needs to register itself with this
>>> cache. I presume PyQt already maintains a similar dictionary so that
>>> it can translate between Qt's internal memory addresses and PyQt's
>>> wrapper objects. Would it not be straightforward to implement my
>>> workaround from within PyQt?
>>
>> Not straightforward, but certainly worth thinking about.
>>
>> Do you have something small I can use as a test case?
>>
>> Phil


More information about the PyQt mailing list