eric6/E5Graphics/E5ArrowItem.py

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

eric ide

mercurial