Sat, 10 Apr 2021 18:38:27 +0200
Applied some more code simplifications suggested by the new Simplify checker (super(Foo, self) => super()).
# -*- coding: utf-8 -*- # Copyright (c) 2007 - 2021 Detlev Offenbach <detlev@die-offenbachs.de> # """ Module implementing a graphics item subclass for an arrow. """ import math from PyQt5.QtCore import QPointF, QRectF, QSizeF, QLineF, Qt from PyQt5.QtGui import QPen, QPolygonF, QColor from PyQt5.QtWidgets import QAbstractGraphicsShapeItem, QGraphicsItem, QStyle NormalArrow = 1 WideArrow = 2 ArrowheadAngleFactor = 0.26179938779914941 # That is: 0.5 * math.atan(math.sqrt(3.0) / 3.0) class E5ArrowItem(QAbstractGraphicsShapeItem): """ Class implementing an arrow graphics item subclass. """ def __init__(self, origin=None, end=None, filled=False, arrowType=NormalArrow, colors=None, parent=None): """ Constructor @param origin origin of the arrow @type QPointF @param end end point of the arrow @type QPointF @param filled flag indicating a filled arrow head @type bool @param arrowType arrow type @type int, one of NormalArrow, WideArrow @param colors tuple containing the foreground and background colors @type tuple of (QColor, QColor) @param parent reference to the parent object @type QGraphicsItem """ super().__init__(parent) self._origin = QPointF() if origin is None else QPointF(origin) self._end = QPointF() if end is None else QPointF(end) self._filled = filled self._type = arrowType if colors is None: self._colors = (QColor(Qt.GlobalColor.black), QColor(Qt.GlobalColor.white)) else: self._colors = colors self._halfLength = 13.0 self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsMovable, True) self.setFlag(QGraphicsItem.GraphicsItemFlag.ItemIsSelectable, True) def setPoints(self, xa, ya, xb, yb): """ Public method to set the start and end points of the line. <b>Note:</b> This method does not redraw the item. @param xa x-coordinate of the start point (float) @param ya y-coordinate of the start point (float) @param xb x-coordinate of the end point (float) @param yb y-coordinate of the end point (float) """ self._origin = QPointF(xa, ya) self._end = QPointF(xb, yb) def setStartPoint(self, x, y): """ Public method to set the start point. <b>Note:</b> This method does not redraw the item. @param x x-coordinate of the start point (float) @param y y-coordinate of the start point (float) """ self._origin = QPointF(x, y) def setEndPoint(self, x, y): """ Public method to set the end point. <b>Note:</b> This method does not redraw the item. @param x x-coordinate of the end point (float) @param y y-coordinate of the end point (float) """ self._end = QPointF(x, y) def boundingRect(self): """ Public method to return the bounding rectangle. @return bounding rectangle (QRectF) """ extra = self._halfLength / 2.0 return QRectF(self._origin, QSizeF(self._end.x() - self._origin.x(), self._end.y() - self._origin.y()) ).normalized().adjusted(-extra, -extra, extra, extra) def paint(self, painter, option, widget=None): """ Public method to paint the item in local coordinates. @param painter reference to the painter object (QPainter) @param option style options (QStyleOptionGraphicsItem) @param widget optional reference to the widget painted on (QWidget) """ if ( (option.state & QStyle.StateFlag.State_Selected) == QStyle.State(QStyle.StateFlag.State_Selected) ): width = 2 else: width = 1 # draw the line first line = QLineF(self._origin, self._end) painter.setPen( QPen(self._colors[0], width, Qt.PenStyle.SolidLine, Qt.PenCapStyle.FlatCap, Qt.PenJoinStyle.MiterJoin)) painter.drawLine(line) # draw the arrow head arrowAngle = self._type * ArrowheadAngleFactor slope = math.atan2(line.dy(), line.dx()) # Calculate left arrow point arrowSlope = slope + arrowAngle a1 = QPointF(self._end.x() - self._halfLength * math.cos(arrowSlope), self._end.y() - self._halfLength * math.sin(arrowSlope)) # Calculate right arrow point arrowSlope = slope - arrowAngle a2 = QPointF(self._end.x() - self._halfLength * math.cos(arrowSlope), self._end.y() - self._halfLength * math.sin(arrowSlope)) if self._filled: painter.setBrush(self._colors[0]) else: painter.setBrush(self._colors[1]) polygon = QPolygonF() polygon.append(line.p2()) polygon.append(a1) polygon.append(a2) painter.drawPolygon(polygon)