source: orange/Orange/OrangeCanvas/canvas/items/graphicspathobject.py @ 11160:6bfea7812243

Revision 11160:6bfea7812243, 3.4 KB checked in by Ales Erjavec <ales.erjavec@…>, 18 months ago (diff)

Refactored GraphicsPathObject and ControlPoint/Rect/Line into two new modules.

Line 
1from PyQt4.QtGui import QGraphicsObject, QPainterPath, QPainterPathStroker, \
2                        QBrush, QPen
3
4from PyQt4.QtCore import Qt, QPointF, pyqtSignal as Signal
5
6
7class GraphicsPathObject(QGraphicsObject):
8    """A QGraphicsObject subclass implementing an interface similar to
9    QGraphicsPathItem, and also adding a positionChanged() signal
10
11    """
12
13    positionChanged = Signal([], ["QPointF"])
14
15    def __init__(self, parent=None, **kwargs):
16        QGraphicsObject.__init__(self, parent, **kwargs)
17        self.setFlag(QGraphicsObject.ItemSendsGeometryChanges)
18
19        self.__path = QPainterPath()
20        self.__brush = QBrush(Qt.NoBrush)
21        self.__pen = QPen()
22        self.__boundingRect = None
23
24    def setPath(self, path):
25        """Set the items `path` (:class:`QPainterPath`).
26        """
27        if not isinstance(path, QPainterPath):
28            raise TypeError("%r, 'QPainterPath' expected" % type(path))
29
30        if self.__path != path:
31            self.prepareGeometryChange()
32            # Need to store a copy of object so the shape can't be mutated
33            # without properly updating the geometry.
34            self.__path = QPainterPath(path)
35            self.__boundingRect = None
36            self.update()
37
38    def path(self):
39        """Return the items path.
40        """
41        return QPainterPath(self.__path)
42
43    def setBrush(self, brush):
44        """Set the items `brush` (:class:`QBrush`)
45        """
46        if not isinstance(brush, QBrush):
47            brush = QBrush(brush)
48
49        if self.__brush != brush:
50            self.__brush = QBrush(brush)
51            self.update()
52
53    def brush(self):
54        """Return the items brush.
55        """
56        return QBrush(self.__brush)
57
58    def setPen(self, pen):
59        """Set the items outline `pen` (:class:`QPen`).
60        """
61        if not isinstance(pen, QPen):
62            pen = QPen(pen)
63
64        if self.__pen != pen:
65            self.prepareGeometryChange()
66            self.__pen = QPen(pen)
67            self.__boundingRect = None
68            self.update()
69
70    def pen(self):
71        """Return the items pen.
72        """
73        return QPen(self.__pen)
74
75    def paint(self, painter, option, widget=None):
76        if self.__path.isEmpty():
77            return
78
79        painter.save()
80        painter.setPen(self.__pen)
81        painter.setBrush(self.__brush)
82        painter.drawPath(self.__path)
83        painter.restore()
84
85    def boundingRect(self):
86        if self.__boundingRect is None:
87            br = self.__path.controlPointRect()
88            pen_w = self.__pen.widthF()
89            self.__boundingRect = br.adjusted(-pen_w, -pen_w, pen_w, pen_w)
90
91        return self.__boundingRect
92
93    def shape(self):
94        return shapeFromPath(self.__path, self.__pen)
95
96    def itemChange(self, change, value):
97        if change == QGraphicsObject.ItemPositionHasChanged:
98            self.positionChanged.emit()
99            self.positionChanged[QPointF].emit(value.toPyObject())
100
101        return QGraphicsObject.itemChange(self, change, value)
102
103
104def shapeFromPath(path, pen):
105    """Create a QPainterPath shape from the `path` drawn with `pen`.
106    """
107    stroker = QPainterPathStroker()
108    stroker.setCapStyle(pen.capStyle())
109    stroker.setJoinStyle(pen.joinStyle())
110    stroker.setMiterLimit(pen.miterLimit())
111    stroker.setWidth(max(pen.widthF(), 1e-9))
112
113    shape = stroker.createStroke(path)
114    shape.addPath(path)
115
116    return shape
Note: See TracBrowser for help on using the repository browser.