UIGraphicsItem.py 4.56 KB
Newer Older
1
from ..Qt import QtGui, QtCore, USE_PYSIDE
2
import weakref
3
from .GraphicsObject import GraphicsObject
Luke Campagnola's avatar
Luke Campagnola committed
4
5
if not USE_PYSIDE:
    import sip
6
7
8

__all__ = ['UIGraphicsItem']
class UIGraphicsItem(GraphicsObject):
9
10
    """
    Base class for graphics items with boundaries relative to a GraphicsView or ViewBox.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
    The purpose of this class is to allow the creation of GraphicsItems which live inside 
    a scalable view, but whose boundaries will always stay fixed relative to the view's boundaries.
    For example: GridItem, InfiniteLine
    
    The view can be specified on initialization or it can be automatically detected when the item is painted.
    
    NOTE: Only the item's boundingRect is affected; the item is not transformed in any way. Use viewRangeChanged
    to respond to changes in the view.
    """
    
    #sigViewChanged = QtCore.Signal(object)  ## emitted whenever the viewport coords have changed
    
    def __init__(self, bounds=None, parent=None):
        """
25
26
27
28
29
        ============== =============================================================================
        **Arguments:**
        bounds         QRectF with coordinates relative to view box. The default is QRectF(0,0,1,1),
                       which means the item will have the same bounds as the view.
        ============== =============================================================================
30
31
32
33
34
35
36
37
38
39
        """
        GraphicsObject.__init__(self, parent)
        self.setFlag(self.ItemSendsScenePositionChanges)
            
        if bounds is None:
            self._bounds = QtCore.QRectF(0, 0, 1, 1)
        else:
            self._bounds = bounds
            
        self._boundingRect = None
40
        self._updateView()
41
42
43
44
45
46
47
48
        
    def paint(self, *args):
        ## check for a new view object every time we paint.
        #self.updateView()
        pass
    
    def itemChange(self, change, value):
        ret = GraphicsObject.itemChange(self, change, value)
Luke Campagnola's avatar
Luke Campagnola committed
49
50
51
52
53
54
            
        ## workaround for pyqt bug:
        ## http://www.riverbankcomputing.com/pipermail/pyqt/2012-August/031818.html
        if not USE_PYSIDE and change == self.ItemParentChange and isinstance(ret, QtGui.QGraphicsItem):
            ret = sip.cast(ret, QtGui.QGraphicsItem)
        
55
        if change == self.ItemScenePositionHasChanged:
56
57
58
            self.setNewBounds()
        return ret
    
59
60
    #def updateView(self):
        ### called to see whether this item has a new view to connect to
61
        
62
63
64
65
66
        ### check for this item's current viewbox or view widget
        #view = self.getViewBox()
        #if view is None:
            ##print "  no view"
            #return
67
            
68
69
70
        #if self._connectedView is not None and view is self._connectedView():
            ##print "  already have view", view
            #return
71
            
72
73
74
75
76
77
        ### disconnect from previous view
        #if self._connectedView is not None:
            #cv = self._connectedView()
            #if cv is not None:
                ##print "disconnect:", self
                #cv.sigRangeChanged.disconnect(self.viewRangeChanged)
78
            
79
80
81
82
83
84
        ### connect to new view
        ##print "connect:", self
        #view.sigRangeChanged.connect(self.viewRangeChanged)
        #self._connectedView = weakref.ref(view)
        #self.setNewBounds()

85
86
87
88
89
90
91
92
93
    def boundingRect(self):
        if self._boundingRect is None:
            br = self.viewRect()
            if br is None:
                return QtCore.QRectF()
            else:
                self._boundingRect = br
        return QtCore.QRectF(self._boundingRect)
    
94
    def dataBounds(self, axis, frac=1.0, orthoRange=None):
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
        """Called by ViewBox for determining the auto-range bounds.
        By default, UIGraphicsItems are excluded from autoRange."""
        return None

    def viewRangeChanged(self):
        """Called when the view widget/viewbox is resized/rescaled"""
        self.setNewBounds()
        self.update()
        
    def setNewBounds(self):
        """Update the item's bounding rect to match the viewport"""
        self._boundingRect = None  ## invalidate bounding rect, regenerate later if needed.
        self.prepareGeometryChange()


    def setPos(self, *args):
        GraphicsObject.setPos(self, *args)
        self.setNewBounds()
        
    def mouseShape(self):
        """Return the shape of this item after expanding by 2 pixels"""
        shape = self.shape()
        ds = self.mapToDevice(shape)
        stroker = QtGui.QPainterPathStroker()
        stroker.setWidh(2)
        ds2 = stroker.createStroke(ds).united(ds)
        return self.mapFromDevice(ds2)
        
        
124