Remove use of GraphicsScene._addressCache in translateGraphicsItem

Use QGraphicsItem.toQGrapicsObject on the item instead.

This probably is not even needed since PyQt 4.9
This commit is contained in:
Ales Erjavec 2018-12-20 18:40:36 +01:00
parent a76d9daec2
commit 02b7532706
2 changed files with 25 additions and 51 deletions

View File

@ -1,5 +1,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import weakref import weakref
import warnings
from ..Qt import QtCore, QtGui from ..Qt import QtCore, QtGui
from ..Point import Point from ..Point import Point
from .. import functions as fn from .. import functions as fn
@ -88,15 +90,11 @@ class GraphicsScene(QtGui.QGraphicsScene):
@classmethod @classmethod
def registerObject(cls, obj): def registerObject(cls, obj):
""" warnings.warn(
Workaround for PyQt bug in qgraphicsscene.items() "'registerObject' is deprecated and does nothing.",
All subclasses of QGraphicsObject must register themselves with this function. DeprecationWarning, stacklevel=2
(otherwise, mouse interaction with those objects will likely fail) )
"""
if HAVE_SIP and isinstance(obj, sip.wrapper):
cls._addressCache[sip.unwrapinstance(sip.cast(obj, QtGui.QGraphicsItem))] = obj
def __init__(self, clickRadius=2, moveDistance=5, parent=None): def __init__(self, clickRadius=2, moveDistance=5, parent=None):
QtGui.QGraphicsScene.__init__(self, parent) QtGui.QGraphicsScene.__init__(self, parent)
self.setClickRadius(clickRadius) self.setClickRadius(clickRadius)
@ -368,46 +366,15 @@ class GraphicsScene(QtGui.QGraphicsScene):
return ev.isAccepted() return ev.isAccepted()
def items(self, *args): def items(self, *args):
#print 'args:', args
items = QtGui.QGraphicsScene.items(self, *args) items = QtGui.QGraphicsScene.items(self, *args)
## PyQt bug: items() returns a list of QGraphicsItem instances. If the item is subclassed from QGraphicsObject, return self.translateGraphicsItems(items)
## then the object returned will be different than the actual item that was originally added to the scene
items2 = list(map(self.translateGraphicsItem, items))
#if HAVE_SIP and isinstance(self, sip.wrapper):
#items2 = []
#for i in items:
#addr = sip.unwrapinstance(sip.cast(i, QtGui.QGraphicsItem))
#i2 = GraphicsScene._addressCache.get(addr, i)
##print i, "==>", i2
#items2.append(i2)
#print 'items:', items
return items2
def selectedItems(self, *args): def selectedItems(self, *args):
items = QtGui.QGraphicsScene.selectedItems(self, *args) items = QtGui.QGraphicsScene.selectedItems(self, *args)
## PyQt bug: items() returns a list of QGraphicsItem instances. If the item is subclassed from QGraphicsObject, return self.translateGraphicsItems(items)
## then the object returned will be different than the actual item that was originally added to the scene
#if HAVE_SIP and isinstance(self, sip.wrapper):
#items2 = []
#for i in items:
#addr = sip.unwrapinstance(sip.cast(i, QtGui.QGraphicsItem))
#i2 = GraphicsScene._addressCache.get(addr, i)
##print i, "==>", i2
#items2.append(i2)
items2 = list(map(self.translateGraphicsItem, items))
#print 'items:', items
return items2
def itemAt(self, *args): def itemAt(self, *args):
item = QtGui.QGraphicsScene.itemAt(self, *args) item = QtGui.QGraphicsScene.itemAt(self, *args)
## PyQt bug: items() returns a list of QGraphicsItem instances. If the item is subclassed from QGraphicsObject,
## then the object returned will be different than the actual item that was originally added to the scene
#if HAVE_SIP and isinstance(self, sip.wrapper):
#addr = sip.unwrapinstance(sip.cast(item, QtGui.QGraphicsItem))
#item = GraphicsScene._addressCache.get(addr, item)
#return item
return self.translateGraphicsItem(item) return self.translateGraphicsItem(item)
def itemsNearEvent(self, event, selMode=QtCore.Qt.IntersectsItemShape, sortOrder=QtCore.Qt.DescendingOrder, hoverable=False): def itemsNearEvent(self, event, selMode=QtCore.Qt.IntersectsItemShape, sortOrder=QtCore.Qt.DescendingOrder, hoverable=False):
@ -554,10 +521,14 @@ class GraphicsScene(QtGui.QGraphicsScene):
@staticmethod @staticmethod
def translateGraphicsItem(item): def translateGraphicsItem(item):
## for fixing pyqt bugs where the wrong item is returned # This function is intended as a workaround for a problem with older
# versions of PyQt (< 4.9?), where methods returning 'QGraphicsItem *'
# lose the type of the QGraphicsObject subclasses and instead return
# generic QGraphicsItem wrappers.
if HAVE_SIP and isinstance(item, sip.wrapper): if HAVE_SIP and isinstance(item, sip.wrapper):
addr = sip.unwrapinstance(sip.cast(item, QtGui.QGraphicsItem)) obj = item.toGraphicsObject()
item = GraphicsScene._addressCache.get(addr, item) if obj is not None:
item = obj
return item return item
@staticmethod @staticmethod

View File

@ -19,8 +19,8 @@ class GraphicsItem(object):
The GraphicsView system places a lot of emphasis on the notion that the graphics within the scene should be device independent--you should be able to take the same graphics and display them on screens of different resolutions, printers, export to SVG, etc. This is nice in principle, but causes me a lot of headache in practice. It means that I have to circumvent all the device-independent expectations any time I want to operate in pixel coordinates rather than arbitrary scene coordinates. A lot of the code in GraphicsItem is devoted to this task--keeping track of view widgets and device transforms, computing the size and shape of a pixel in local item coordinates, etc. Note that in item coordinates, a pixel does not have to be square or even rectangular, so just asking how to increase a bounding rect by 2px can be a rather complex task. The GraphicsView system places a lot of emphasis on the notion that the graphics within the scene should be device independent--you should be able to take the same graphics and display them on screens of different resolutions, printers, export to SVG, etc. This is nice in principle, but causes me a lot of headache in practice. It means that I have to circumvent all the device-independent expectations any time I want to operate in pixel coordinates rather than arbitrary scene coordinates. A lot of the code in GraphicsItem is devoted to this task--keeping track of view widgets and device transforms, computing the size and shape of a pixel in local item coordinates, etc. Note that in item coordinates, a pixel does not have to be square or even rectangular, so just asking how to increase a bounding rect by 2px can be a rather complex task.
""" """
_pixelVectorGlobalCache = LRUCache(100, 70) _pixelVectorGlobalCache = LRUCache(100, 70)
def __init__(self, register=True): def __init__(self, register=None):
if not hasattr(self, '_qtBaseClass'): if not hasattr(self, '_qtBaseClass'):
for b in self.__class__.__bases__: for b in self.__class__.__bases__:
if issubclass(b, QtGui.QGraphicsItem): if issubclass(b, QtGui.QGraphicsItem):
@ -28,15 +28,18 @@ class GraphicsItem(object):
break break
if not hasattr(self, '_qtBaseClass'): if not hasattr(self, '_qtBaseClass'):
raise Exception('Could not determine Qt base class for GraphicsItem: %s' % str(self)) raise Exception('Could not determine Qt base class for GraphicsItem: %s' % str(self))
self._pixelVectorCache = [None, None] self._pixelVectorCache = [None, None]
self._viewWidget = None self._viewWidget = None
self._viewBox = None self._viewBox = None
self._connectedView = None self._connectedView = None
self._exportOpts = False ## If False, not currently exporting. Otherwise, contains dict of export options. self._exportOpts = False ## If False, not currently exporting. Otherwise, contains dict of export options.
if register: if register is not None and register:
GraphicsScene.registerObject(self) ## workaround for pyqt bug in graphicsscene.items() warnings.warn(
"'register' argument is deprecated and does nothing",
DeprecationWarning, stacklevel=2
)
def getViewWidget(self): def getViewWidget(self):
""" """
Return the view widget for this item. Return the view widget for this item.