|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2007 - 2010 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a graphics item subclass for an arrow. |
|
8 """ |
|
9 |
|
10 from math import * |
|
11 |
|
12 from PyQt4.QtCore import * |
|
13 from PyQt4.QtGui import * |
|
14 |
|
15 NormalArrow = 1 |
|
16 WideArrow = 2 |
|
17 |
|
18 ArrowheadAngleFactor = 0.26179938779914941 # 0.5 * atan(sqrt(3.0) / 3.0) |
|
19 |
|
20 class E5ArrowItem(QAbstractGraphicsShapeItem): |
|
21 """ |
|
22 Class implementing an arrow graphics item subclass. |
|
23 """ |
|
24 def __init__(self, origin = QPointF(), end = QPointF(), |
|
25 filled = False, type = NormalArrow, parent = None): |
|
26 """ |
|
27 Constructor |
|
28 |
|
29 @param origin origin of the arrow (QPointF) |
|
30 @param end end point of the arrow (QPointF) |
|
31 @param filled flag indicating a filled arrow head (boolean) |
|
32 @param type arrow type (NormalArrow, WideArrow) |
|
33 @keyparam parent reference to the parent object (QGraphicsItem) |
|
34 """ |
|
35 QAbstractGraphicsShapeItem.__init__(self, parent) |
|
36 |
|
37 self._origin = origin |
|
38 self._end = end |
|
39 self._filled = filled |
|
40 self._type = type |
|
41 |
|
42 self._halfLength = 13.0 |
|
43 |
|
44 self.setFlag(QGraphicsItem.ItemIsMovable, True) |
|
45 self.setFlag(QGraphicsItem.ItemIsSelectable, True) |
|
46 |
|
47 def setPoints(self, xa, ya, xb, yb): |
|
48 """ |
|
49 Public method to set the start and end points of the line. |
|
50 |
|
51 <b>Note:</b> This method does not redraw the item. |
|
52 |
|
53 @param xa x-coordinate of the start point (float) |
|
54 @param ya y-coordinate of the start point (float) |
|
55 @param xb x-coordinate of the end point (float) |
|
56 @param yb y-coordinate of the end point (float) |
|
57 """ |
|
58 self._origin = QPointF(xa, ya) |
|
59 self._end = QPointF(xb, yb) |
|
60 |
|
61 def setStartPoint(self, x, y): |
|
62 """ |
|
63 Public method to set the start point. |
|
64 |
|
65 <b>Note:</b> This method does not redraw the item. |
|
66 |
|
67 @param x x-coordinate of the start point (float) |
|
68 @param y y-coordinate of the start point (float) |
|
69 """ |
|
70 self._origin = QPointF(x, y) |
|
71 |
|
72 def setEndPoint(self, x, y): |
|
73 """ |
|
74 Public method to set the end point. |
|
75 |
|
76 <b>Note:</b> This method does not redraw the item. |
|
77 |
|
78 @param x x-coordinate of the end point (float) |
|
79 @param y y-coordinate of the end point (float) |
|
80 """ |
|
81 self._end = QPointF(x, y) |
|
82 |
|
83 def boundingRect(self): |
|
84 """ |
|
85 Public method to return the bounding rectangle. |
|
86 |
|
87 @return bounding rectangle (QRectF) |
|
88 """ |
|
89 extra = self._halfLength / 2.0 |
|
90 return QRectF(self._origin, QSizeF(self._end.x() - self._origin.x(), |
|
91 self._end.y() - self._origin.y()))\ |
|
92 .normalized()\ |
|
93 .adjusted(-extra, -extra, extra, extra) |
|
94 |
|
95 def paint(self, painter, option, widget = None): |
|
96 """ |
|
97 Public method to paint the item in local coordinates. |
|
98 |
|
99 @param painter reference to the painter object (QPainter) |
|
100 @param option style options (QStyleOptionGraphicsItem) |
|
101 @param widget optional reference to the widget painted on (QWidget) |
|
102 """ |
|
103 if (option.state & QStyle.State_Selected) == QStyle.State(QStyle.State_Selected): |
|
104 width = 2 |
|
105 else: |
|
106 width = 1 |
|
107 |
|
108 # draw the line first |
|
109 line = QLineF(self._origin, self._end) |
|
110 painter.setPen(QPen(Qt.black, width, Qt.SolidLine, Qt.FlatCap, Qt.MiterJoin)) |
|
111 painter.drawLine(line) |
|
112 |
|
113 # draw the arrow head |
|
114 arrowAngle = self._type * ArrowheadAngleFactor |
|
115 slope = atan2(line.dy(), line.dx()) |
|
116 |
|
117 # Calculate left arrow point |
|
118 arrowSlope = slope + arrowAngle |
|
119 a1 = QPointF(self._end.x() - self._halfLength * cos(arrowSlope), |
|
120 self._end.y() - self._halfLength * sin(arrowSlope)) |
|
121 |
|
122 # Calculate right arrow point |
|
123 arrowSlope = slope - arrowAngle |
|
124 a2 = QPointF(self._end.x() - self._halfLength * cos(arrowSlope), |
|
125 self._end.y() - self._halfLength * sin(arrowSlope)) |
|
126 |
|
127 if self._filled: |
|
128 painter.setBrush(Qt.black) |
|
129 else: |
|
130 painter.setBrush(Qt.white) |
|
131 polygon = QPolygonF() |
|
132 polygon.append(line.p2()) |
|
133 polygon.append(a1) |
|
134 polygon.append(a2) |
|
135 painter.drawPolygon(polygon) |