def mouseMoveEvent(self, event): super(BaseGraphicsView, self).mouseMoveEvent(event) self._mouse_pos = event.pos() if self._is_panning: delta = self.mapToScene(event.pos()) - self.mapToScene( self._last_mouse_pos) self._pan(delta) if self._rubber_rect and self.scene(): if self._is_rubber_rect_selection: current_pos = self.mapToScene(self._mouse_pos) press_pos = self.mapToScene(self._mouse_pressed_pos) if self._rubber_rect not in self.scene().items(): self.scene().addItem(self._rubber_rect) if not self._rubber_rect.isVisible(): self._rubber_rect.setVisible(True) r = QRectF(press_pos.x(), press_pos.y(), current_pos.x() - press_pos.x(), current_pos.y() - press_pos.y()) self._rubber_rect.setRect(r.normalized()) self._auto_pan_controller.update(self.viewport().rect(), event.pos()) self._last_mouse_pos = event.pos()
def resizeEvent(self, event): a = min(self.width(), self.height()) top_left = QPointF() if self._alignment & Qt.AlignTop: top_left.setY(0) elif self._alignment & Qt.AlignVCenter: top_left.setY((self.height() - a) * 0.5) elif self._alignment & Qt.AlignBottom: top_left.setY(self.height() - a) if self._alignment & Qt.AlignLeft: top_left.setX(0) elif self._alignment & Qt.AlignHCenter: top_left.setX((self.width() - a) * 0.5) elif self._alignment & Qt.AlignRight: top_left.setX(self.width() - a) self._bounds = QRectF(top_left, QSize(a, a)) self._knop_bounds.setWidth(a * 0.3) self._knop_bounds.setHeight(a * 0.3) radius = (self._bounds.width() - self._knop_bounds.height()) * 0.5 self._knop_bounds.moveCenter( QPointF(self._bounds.center().x() + self._x * radius, self._bounds.center().y() - self._y * radius))
def generate_svg(svg_file): draw_set = list() bounding_rect = QRectF() for style, path, pathType, id in get_path_order_from_svg_file(svg_file): # We do not load the init rect item which indicates document settings if style.get('display') == 'none': continue if pathType == 'path': svgPath = create_svg_path(path) elif pathType in ('circle', 'ellipse'): svgPath = create_ellipse_path(path) elif pathType == 'rect': svgPath = create_rect_path(path) elif pathType == 'polygon': svgPath = create_polygon_path(path) else: continue bounding_rect = bounding_rect.united(svgPath.boundingRect()) draw_set.append([style, svgPath]) for bundle in draw_set: path = bundle.pop() offset = path.boundingRect().topLeft() - bounding_rect.topLeft() path.translate(path.boundingRect().topLeft() * -1) path.translate(offset) bundle.append(path) return (bounding_rect, draw_set)
def __init__(self, parent=None): super(JoyPad, self).__init__(parent=parent) self._x = 0 self._y = 0 self._bounds = QRectF() self._knop_bounds = QRectF() self._last_pos = QPoint() self._knop_pressed = False self._return_animation = QParallelAnimationGroup(self) self._x_anim = QPropertyAnimation(self, 'x') self._y_anim = QPropertyAnimation(self, 'y') self._alignment = Qt.AlignTop | Qt.AlignLeft self._x_anim.setEndValue(0.0) self._x_anim.setDuration(400) self._x_anim.setEasingCurve(QEasingCurve.OutSine) self._y_anim.setEndValue(0.0) self._y_anim.setDuration(400) self._y_anim.setEasingCurve(QEasingCurve.OutSine) self._return_animation.addAnimation(self._x_anim) self._return_animation.addAnimation(self._y_anim)
def paint(self, painter, option, index): painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform) model = index.model() view = self.parent() if view.hasFocus() and option.state & QStyle.State_MouseOver: painter.setPen(Qt.NoPen) painter.setBrush(Qt.gray) painter.drawRoundedRect(option.rect.adjusted(1, 1, -1, -1), self._ICON_MARGIN, self._ICON_MARGIN) pixmap = model.data(index, Qt.DecorationRole).pixmap(view.iconSize()) pm_rect = QRect( option.rect.topLeft() + QPoint(self._ICON_MARGIN + 1, self._ICON_MARGIN + 1), view.iconSize() - QSize(self._ICON_MARGIN * 2, self._ICON_MARGIN * 2)) painter.drawPixmap(pm_rect, pixmap) if option.state & QStyle.State_Selected: painter.setPen( QPen(Qt.red, 1.0, Qt.SolidLine, Qt.SquareCap, Qt.RoundJoin)) painter.setBrush(Qt.NoBrush) painter.drawRect(option.rect.adjusted(2, 2, -2, -2)) font = view.font() fm = QFontMetrics(font) text = os.path.splitext( os.path.basename(model.data(index, Qt.DisplayRole)))[0] text = fm.elidedText(text, Qt.ElideRight, view.iconSize().width() - 4) text_opt = QTextOption() text_opt.setAlignment(Qt.AlignHCenter) txt_rect = QRectF(QPointF(pm_rect.bottomLeft() + QPoint(0, 1)), QPointF(option.rect.bottomRight() - QPoint(4, 3))) painter.save() painter.setPen(Qt.NoPen) painter.setBrush(QColor(22, 22, 22, 220)) painter.drawRoundedRect(txt_rect.adjusted(-2, -2, 2, 2), 2, 2) painter.restore() painter.setPen(self.parent().palette().color(QPalette.WindowText)) painter.drawText(txt_rect, text, text_opt) font.setPointSize(8) fm = QFontMetrics(font) item = model.itemFromIndex(index) size_text = '%d x %d' % (item.size.width(), item.size.height()) size_rect = fm.boundingRect(option.rect, Qt.AlignLeft | Qt.AlignTop, size_text) size_rect.translate(4, 4) painter.save() painter.setPen(Qt.NoPen) painter.setBrush(QColor(22, 22, 22, 220)) painter.drawRoundedRect(size_rect.adjusted(-2, -2, 2, 2), 2, 2) painter.restore() painter.setFont(font) painter.drawText(size_rect, size_text)
def boundingRect(self): anchor = self.mapFromParent(self.m_chart.mapToPosition(self.m_anchor)) rect = QRectF() rect.setLeft(min(self.m_rect.left(), anchor.x())) rect.setRight(max(self.m_rect.right(), anchor.x())) rect.setTop(min(self.m_rect.top(), anchor.y())) rect.setBottom(max(self.m_rect.bottom(), anchor.y())) return rect
def calculate_start_angle(x1, y1, rx, ry, coordAngle, largeArcFlag, sweep_flag, x2, y2): def dotproduct(v1, v2): return sum((a * b for a, b in zip(v1, v2))) def length(v): return math.sqrt(dotproduct(v, v)) def angle(v1, v2): return math.acos(dotproduct(v1, v2) / (length(v1) * length(v2))) rotated_x1 = math.cos(math.radians(coordAngle)) * ( (x1 - x2) / 2) + math.sin(math.radians(coordAngle)) * ((y1 - y2) / 2) rotated_y1 = -math.sin(math.radians(coordAngle)) * ( (x1 - x2) / 2) + math.cos(math.radians(coordAngle)) * ((y1 - y2) / 2) delta = rotated_x1**2 / rx**2 + rotated_y1**2 / ry**2 if delta > 1: rx *= math.sqrt(delta) ry *= math.sqrt(delta) _a = (rx**2 * ry**2 - rx**2 * rotated_y1**2 - ry**2 * rotated_x1**2) _b = (rx**2 * rotated_y1**2 + ry**2 * rotated_x1**2) var = math.sqrt(_a / _b) if largeArcFlag == sweep_flag: var *= -1 ccx = var * (rx * rotated_y1 / ry) ccy = var * -(ry * rotated_x1 / rx) cx = math.cos(math.radians(coordAngle)) * ccx - math.sin( math.radians(coordAngle)) * ccy + (x1 + x2) / 2 cy = math.sin(math.radians(coordAngle)) * ccx + math.cos( math.radians(coordAngle)) * ccy + (y1 + y2) / 2 start_angle = math.degrees( angle([1, 0], [(rotated_x1 - ccx) / rx, (rotated_y1 - ccy) / ry])) start_angle_sign = 1 * (rotated_y1 - ccy) / ry - 0 * (rotated_x1 - ccx) / rx if start_angle_sign == 0: start_angle_sign = 1.0 start_angle_sign /= abs(start_angle_sign) start_angle *= start_angle_sign try: sweep_angle = math.degrees( angle([(rotated_x1 - ccx) / rx, (rotated_y1 - ccy) / ry], [(-rotated_x1 - ccx) / rx, (-rotated_y1 - ccy) / ry])) except ValueError: sweep_angle = 180.0 sweep_angle_sign = (rotated_x1 - ccx) / rx * (-rotated_y1 - ccy) / ry - \ (rotated_y1 - ccy) / ry * (-rotated_x1 - ccx) / rx if sweep_angle_sign == 0: sweep_angle_sign = 1.0 sweep_angle_sign /= abs(sweep_angle_sign) sweep_angle *= sweep_angle_sign if sweep_flag == 0 and sweep_angle > 0: sweep_angle -= 360 elif sweep_flag == 1 and sweep_angle < 0: sweep_angle += 360 rect = QRectF(0, 0, rx * 2, ry * 2) rect.moveCenter(QPointF(cx, cy)) return (start_angle, sweep_angle, rect)
def __init__(self, chart): super().__init__(chart) self.m_chart = chart self.m_text = "" self.m_textRect = QRectF() self.m_rect = QRectF() self.m_anchor = QPointF() self.m_font = QFont()
def setText(self, text): self.m_text = text metrics = QFontMetrics(self.m_font) self.m_textRect = QRectF( metrics.boundingRect(QRect(0, 0, 150, 150), Qt.AlignLeft, self.m_text)) self.m_textRect.translate(5, 5) self.prepareGeometryChange() self.m_rect = self.m_textRect.adjusted(-5, -5, 5, 5)
def get_items_by_z_value_order(self, classes_tuple=None, rect=QRectF()): """ Returns the items of the passed class :param classes_tuple: :param rect: :return: """ def cmp_zvalue(x, y): x_val = x.zValue() y_val = y.zValue() if x_val > y_val: return 1 elif x_val < y_val: return -1 else: return 0 if classes_tuple is not None: items = filter(lambda x: isinstance(x, classes_tuple), rect.isValid() and self.items(rect) or self.items()) else: items = self.items() if items: items.sort(key=lambda x: x.zValue()) return items
def drawSizeInfo(self): sizeInfoAreaWidth = 200 sizeInfoAreaHeight = 30 spacing = 5 rect = self.selectedArea.normalized() sizeInfoArea = QRect(rect.left(), rect.top() - spacing - sizeInfoAreaHeight, sizeInfoAreaWidth, sizeInfoAreaHeight) if sizeInfoArea.top() < 0: sizeInfoArea.moveTopLeft(rect.topLeft() + QPoint(spacing, spacing)) if sizeInfoArea.right() >= self.screenPixel.width(): sizeInfoArea.moveTopLeft(rect.topLeft() - QPoint(spacing, spacing) - QPoint(sizeInfoAreaWidth, 0)) if sizeInfoArea.left() < spacing: sizeInfoArea.moveLeft(spacing) if sizeInfoArea.top() < spacing: sizeInfoArea.moveTop(spacing) self.itemsToRemove.append( self.graphicsScene.addRect(QRectF(sizeInfoArea), QPen(Qt.white), QBrush(Qt.black))) sizeInfo = self.graphicsScene.addSimpleText(' {0} x {1}'.format( rect.width() * self.scale, rect.height() * self.scale)) sizeInfo.setPos(sizeInfoArea.topLeft() + QPoint(0, 2)) sizeInfo.setPen(QPen(QColor(255, 255, 255), 2)) self.itemsToRemove.append(sizeInfo)
def resetView(self): self.zoomSlider.setValue(250) self.rotateSlider.setValue(0) self.setupTransform() self.graphicsView.ensureVisible(QRectF(0, 0, 0, 0)) self.resetButton.setEnabled(False)
def __init__(self, parent=None): super(BezierCurveItem, self).__init__(parent) self._pen = QPen(Qt.green, 2, Qt.SolidLine) self._rect = QRectF() self._bounding_rect = None self._points = list() # self._theme = None self.setZValue(-1)
def drawBackground(self, painter, rect): """ Override method to draw view custom background image """ if not self.background_image: return super(GridBackgroundImageView, self).drawBackground(painter, rect) super(GridBackgroundImageView, self).drawBackground(painter, rect) painter.drawImage(self.sceneRect(), self.background_image, QRectF(self.background_image.rect()))
def resizeEvent(self, event): if self.scene() is not None: self.scene().setSceneRect(QRectF(QRect(QPoint(0, 0), event.size()))) self.m_chart.resize(QSizeF(event.size())) self.m_coordX.setPos( self.m_chart.size().width() / 2 - 50, self.m_chart.size().height() - 20 ) self.m_coordY.setPos( self.m_chart.size().width() / 2 + 50, self.m_chart.size().height() - 20 ) for callout in self.m_callouts: callout.updateGeometry() super().resizeEvent(event)
def _zoom(self, scale_factor): self._factor = round( self.matrix().scale(scale_factor, scale_factor).mapRect(QRectF(0, 0, 1, 1)).width(), 1) if hasattr(self.scene(), 'grid_size'): if self._factor < (self._min_scale + 0.4): self.scene().grid_size = 20 else: self.scene().grid_size = 10 if self._factor < self._min_scale or self._factor > self._max_scale: return self.scale(scale_factor, scale_factor) self._scale *= scale_factor
def redraw(self): self.graphicsScene.clear() # draw screenshot self.graphicsScene.addPixmap(self.screenPixel) # prepare for drawing selected area rect = QRectF(self.selectedArea) rect = rect.normalized() topLeftPoint = rect.topLeft() topRightPoint = rect.topRight() bottomLeftPoint = rect.bottomLeft() bottomRightPoint = rect.bottomRight() topMiddlePoint = (topLeftPoint + topRightPoint) / 2 leftMiddlePoint = (topLeftPoint + bottomLeftPoint) / 2 bottomMiddlePoint = (bottomLeftPoint + bottomRightPoint) / 2 rightMiddlePoint = (topRightPoint + bottomRightPoint) / 2 # draw the picture mask mask = QColor(0, 0, 0, 155) if self.selectedArea == QRect(): self.graphicsScene.addRect(0, 0, self.screenPixel.width(), self.screenPixel.height(), QPen(Qt.NoPen), mask) else: self.graphicsScene.addRect(0, 0, self.screenPixel.width(), topRightPoint.y(), QPen(Qt.NoPen), mask) self.graphicsScene.addRect(0, topLeftPoint.y(), topLeftPoint.x(), rect.height(), QPen(Qt.NoPen), mask) self.graphicsScene.addRect( topRightPoint.x(), topRightPoint.y(), self.screenPixel.width() - topRightPoint.x(), rect.height(), QPen(Qt.NoPen), mask) self.graphicsScene.addRect( 0, bottomLeftPoint.y(), self.screenPixel.width(), self.screenPixel.height() - bottomLeftPoint.y(), QPen(Qt.NoPen), mask) # draw the toolBar if self.action != ACTION_SELECT: spacing = 5 # show the toolbar first, then move it to the correct position # because the width of it may be wrong if this is the first time it shows self.tooBar.show() dest = QPointF(rect.bottomRight() - QPointF(self.tooBar.width(), 0) - QPointF(spacing, -spacing)) if dest.x() < spacing: dest.setX(spacing) pen_set_bar_height = self.penSetBar.height( ) if self.penSetBar is not None else 0 if dest.y() + self.tooBar.height( ) + pen_set_bar_height >= self.height(): if rect.top() - self.tooBar.height( ) - pen_set_bar_height < spacing: dest.setY(rect.top() + spacing) else: dest.setY(rect.top() - self.tooBar.height() - pen_set_bar_height - spacing) self.tooBar.move(self.mapToGlobal(dest.toPoint())) if self.penSetBar is not None: self.penSetBar.show() _pen_point = QPoint(dest.toPoint() + QPoint(0, self.tooBar.height() + spacing)) self.penSetBar.move(self.mapToGlobal(_pen_point)) if self.action == ACTION_TEXT: self.penSetBar.showFontWidget() else: self.penSetBar.showPenWidget() else: self.tooBar.hide() if self.penSetBar is not None: self.penSetBar.hide() # draw the list for step in self.drawListResult: self.drawOneStep(step) if self.drawListProcess is not None: self.drawOneStep(self.drawListProcess) if self.action != ACTION_TEXT: self.drawListProcess = None # if self.selectedArea != QRect(): # self.itemsToRemove = [] # # draw the selected rectangle # pen = QPen(QColor(0, 255, 255), 2) # self.itemsToRemove.append(self.graphicsScene.addRect(rect, pen)) # # draw the drag point # radius = QPoint(3, 3) # brush = QBrush(QColor(0, 255, 255)) # self.itemsToRemove.append( # self.graphicsScene.addEllipse(QRectF(topLeftPoint - radius, topLeftPoint + radius), pen, brush)) # self.itemsToRemove.append( # self.graphicsScene.addEllipse(QRectF(topMiddlePoint - radius, topMiddlePoint + radius), pen, brush)) # self.itemsToRemove.append( # self.graphicsScene.addEllipse(QRectF(topRightPoint - radius, topRightPoint + radius), pen, brush)) # self.itemsToRemove.append( # self.graphicsScene.addEllipse(QRectF(leftMiddlePoint - radius, leftMiddlePoint + radius), pen, brush)) # self.itemsToRemove.append( # self.graphicsScene.addEllipse(QRectF(rightMiddlePoint - radius, rightMiddlePoint + radius), pen, brush)) # self.itemsToRemove.append( # self.graphicsScene.addEllipse(QRectF(bottomLeftPoint - radius, bottomLeftPoint + radius), pen, brush)) # self.itemsToRemove.append( # self.graphicsScene.addEllipse(QRectF(bottomMiddlePoint - radius, bottomMiddlePoint + radius), pen, brush)) # self.itemsToRemove.append( # self.graphicsScene.addEllipse(QRectF(bottomRightPoint - radius, bottomRightPoint + radius), pen, brush)) # draw the textedit if self.textPosition is not None: textSpacing = 50 position = QPoint() if self.textPosition.x() + self.textInput.width( ) >= self.screenPixel.width(): position.setX(self.textPosition.x() - self.textInput.width()) else: position.setX(self.textPosition.x()) if self.textRect is not None: if self.textPosition.y() + self.textInput.height( ) + self.textRect.height() >= self.screenPixel.height(): position.setY(self.textPosition.y() - self.textInput.height() - self.textRect.height()) else: position.setY(self.textPosition.y() + self.textRect.height()) else: if self.textPosition.y() + self.textInput.height( ) >= self.screenPixel.height(): position.setY(self.textPosition.y() - self.textInput.height()) else: position.setY(self.textPosition.y()) self.textInput.move(self.mapToGlobal(position)) self.textInput.show() # self.textInput.getFocus() # draw the magnifier if self.action == ACTION_SELECT: self.drawMagnifier() if self.mousePressed: self.drawSizeInfo() if self.action == ACTION_MOVE_SELECTED: self.drawSizeInfo()
def create_drop_indicator_pixmap(palette, size, drop_area): border_color = palette.color(QPalette.Active, QPalette.Highlight) background_color = palette.color(QPalette.Active, QPalette.Base) area_background_color = palette.color(QPalette.Active, QPalette.Highlight).lighter(150) pm = QPixmap(size.width(), size.height()) pm.fill(QColor(0, 0, 0, 0)) painter = QPainter(pm) pen = painter.pen() base_rect = QRectF(pm.rect()) painter.fillRect(base_rect, background_color) painter.save() area_rect = QRectF() area_line = QLineF() gradient = QLinearGradient() if drop_area == DropArea.TopDropArea: area_rect = QRectF(base_rect.x(), base_rect.y(), base_rect.width(), base_rect.height() * 0.5) area_line = QLineF(area_rect.bottomLeft(), area_rect.bottomRight()) gradient.setStart(area_rect.topLeft()) gradient.setFinalStop(area_rect.bottomLeft()) gradient.setColorAt(0, area_background_color) gradient.setColorAt(1, area_background_color.lighter(120)) elif drop_area == DropArea.RightDropArea: area_rect = QRectF(base_rect.width() * 0.5, base_rect.y(), base_rect.width() * 0.5, base_rect.height()) area_line = QLineF(area_rect.topLeft(), area_rect.bottomLeft()) gradient.setStart(area_rect.topLeft()) gradient.setFinalStop(area_rect.topRight()) gradient.setColorAt(0, area_background_color.lighter(120)) gradient.setColorAt(1, area_background_color) elif drop_area == DropArea.BottomDropArea: area_rect = QRectF(base_rect.x(), base_rect.height() * 0.5, base_rect.width(), base_rect.height() * 0.5) area_line = QLineF(area_rect.topLeft(), area_rect.topRight()) gradient.setStart(area_rect.topLeft()) gradient.setFinalStop(area_rect.bottomLeft()) gradient.setColorAt(0, area_background_color.lighter(120)) gradient.setColorAt(1, area_background_color) elif drop_area == DropArea.LeftDropArea: area_rect = QRectF(base_rect.x(), base_rect.y(), base_rect.width() * 0.5, base_rect.height()) area_line = QLineF(area_rect.topRight(), area_rect.bottomRight()) gradient.setStart(area_rect.topLeft()) gradient.setFinalStop(area_rect.topRight()) gradient.setColorAt(0, area_background_color) gradient.setColorAt(1, area_background_color.lighter(120)) if area_rect.isValid(): painter.fillRect(area_rect, gradient) pen = painter.pen() pen.setColor(border_color) pen.setStyle(Qt.DashLine) painter.setPen(pen) painter.drawLine(area_line) painter.restore() painter.save() pen = painter.pen() pen.setColor(border_color) pen.setWidth(1) painter.setPen(pen) painter.drawRect(base_rect.adjusted(0, 0, -pen.width(), -pen.width())) painter.restore() return pm
def ui(self): self._central_layout = layouts.VerticalLayout(margins=(0, 0, 0, 0), spacing=0) self.setLayout(self._central_layout) self._top_widget = QWidget() self._top_layout = layouts.VerticalLayout(margins=(0, 0, 0, 0), spacing=0) self._top_widget.setLayout(self._top_layout) for r in self._resizers: r.setParent(self) r.windowResizedFinished.connect(self.dialogResizedFinished) self.set_resize_directions() self._dragger = dragger.DialogDragger(parent=self) self._dragger.setVisible(self.is_frameless()) self._top_layout.addWidget(self._dragger) self.main_widget = DialogContents() self.main_layout = self.get_main_layout() self.main_widget.setLayout(self.main_layout) self.logo_view = QGraphicsView() self.logo_view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.logo_view.setMaximumHeight(100) self._logo_scene = QGraphicsScene() self._logo_scene.setSceneRect(QRectF(0, 0, 2000, 100)) self.logo_view.setScene(self._logo_scene) self.logo_view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.logo_view.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self.logo_view.setFocusPolicy(Qt.NoFocus) if self._has_title and self._title_pixmap: self._logo_scene.addPixmap(self._title_pixmap) self._top_layout.addWidget(self.logo_view) title_background_pixmap = self._get_title_pixmap() if self._has_title and title_background_pixmap: self._logo_scene.addPixmap(title_background_pixmap) self._top_layout.addWidget(self.logo_view) else: self.logo_view.setVisible(False) grid_layout = layouts.GridLayout() grid_layout.setHorizontalSpacing(0) grid_layout.setVerticalSpacing(0) grid_layout.setContentsMargins(0, 0, 0, 0) grid_layout.addWidget(self._top_widget, 1, 1, 1, 1) grid_layout.addWidget(self.main_widget, 2, 1, 1, 1) grid_layout.addWidget(self._top_left_resizer, 0, 0, 1, 1) grid_layout.addWidget(self._top_resizer, 0, 1, 1, 1) grid_layout.addWidget(self._top_right_resizer, 0, 2, 1, 1) grid_layout.addWidget(self._left_resizer, 1, 0, 2, 1) grid_layout.addWidget(self._right_resizer, 1, 2, 2, 1) grid_layout.addWidget(self._bottom_left_resizer, 3, 0, 1, 1) grid_layout.addWidget(self._bottom_resizer, 3, 1, 1, 1) grid_layout.addWidget(self._bottom_right_resizer, 3, 2, 1, 1) grid_layout.setColumnStretch(1, 1) grid_layout.setRowStretch(2, 1) # Shadow effect for dialog # BUG: This causes some rendering problems when using other shadow effects in child widgets of the window # BUG: Also detected problems when updating wigets (tree views, web browsers, etc) # https://bugreports.qt.io/browse/QTBUG-35196 # shadow_effect = QGraphicsDropShadowEffect(self) # shadow_effect.setBlurRadius(qtutils.dpi_scale(15)) # shadow_effect.setColor(QColor(0, 0, 0, 150)) # shadow_effect.setOffset(qtutils.dpi_scale(0)) # self.setGraphicsEffect(shadow_effect) self._central_layout.addLayout(grid_layout) for r in self._resizers: r.windowResizedFinished.connect(self.dialogResizedFinished) if self._size: self.resize(self._size[0], self._size[1])
def paint(self, painter, option, widget): fillColor = self.color if option.state & QStyle.State_Selected: fillColor = self.color.darker(150) if option.state & QStyle.State_MouseOver: fillColor = fillColor.lighter(125) lod = option.levelOfDetailFromTransform(painter.worldTransform()) if lod < 0.2: if lod < 0.125: painter.fillRect(QRectF(0, 0, 110, 70), fillColor) return b = painter.brush() painter.setBrush(fillColor) painter.drawRect(13, 13, 97, 57) painter.setBrush(b) return oldPen = painter.pen() pen = oldPen width = 0 if option.state & QStyle.State_Selected: width += 2 pen.setWidth(width) b = painter.brush() painter.setBrush( QBrush( fillColor.darker(120 if (option.state & QStyle.State_Sunken) else 100))) painter.drawRect(QRect(14, 14, 79, 39)) painter.setBrush(b) if lod >= 1: painter.setPen(QPen(Qt.gray, 1)) painter.drawLine(15, 54, 94, 54) painter.drawLine(94, 53, 94, 15) painter.setPen(QPen(Qt.black, 0)) # Draw text if lod >= 2: font = QFont("Times", 10) font.setStyleStrategy(QFont.ForceOutline) painter.setFont(font) painter.save() painter.scale(0.1, 0.1) painter.drawText( 170, 180, "Model: VSC-2000 (Very Small Chip) at {}x{}".format( self.x, self.y)) painter.drawText(170, 200, "Serial number: DLWR-WEER-123L-ZZ33-SDSJ") painter.drawText(170, 220, "Manufacturer: Chip Manufacturer") painter.restore() # Draw lines lines = [] # QVarLengthArray < QLineF, 36 > if lod >= 0.5: for i in range( 0, 11, 1 if lod > 0.5 else 2): # (int i = 0 i <= 10 i += (1 if lod > 0.5 else 2)): lines.append(QLineF(18 + 7 * i, 13, 18 + 7 * i, 5)) lines.append(QLineF(18 + 7 * i, 54, 18 + 7 * i, 62)) for i in range(0, 6, 1 if lod > 0.5 else 2): # (int i = 0 i <= 6 i += (lod > 0.5 ? 1: 2)) { lines.append(QLineF(5, 18 + i * 5, 13, 18 + i * 5)) lines.append(QLineF(94, 18 + i * 5, 102, 18 + i * 5)) if lod >= 0.4: lineData = [ QLineF(25, 35, 35, 35), QLineF(35, 30, 35, 40), QLineF(35, 30, 45, 35), QLineF(35, 40, 45, 35), QLineF(45, 30, 45, 40), QLineF(45, 35, 55, 35) ] lines.extend(lineData) painter.drawLines(lines) # Draw red ink if len(self.stuff) > 1: p = painter.pen() painter.setPen( QPen(Qt.red, 1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.setBrush(Qt.NoBrush) path = QPainterPath path.moveTo(self.stuff[0]) for i in range(1, len(self.stuff)): path.lineTo(self.stuff[i]) painter.drawPath(path) painter.setPen(p) """
class JoyPad(QWidget, object): xChanged = Signal(float) yChanged = Signal(float) def __init__(self, parent=None): super(JoyPad, self).__init__(parent=parent) self._x = 0 self._y = 0 self._bounds = QRectF() self._knop_bounds = QRectF() self._last_pos = QPoint() self._knop_pressed = False self._return_animation = QParallelAnimationGroup(self) self._x_anim = QPropertyAnimation(self, 'x') self._y_anim = QPropertyAnimation(self, 'y') self._alignment = Qt.AlignTop | Qt.AlignLeft self._x_anim.setEndValue(0.0) self._x_anim.setDuration(400) self._x_anim.setEasingCurve(QEasingCurve.OutSine) self._y_anim.setEndValue(0.0) self._y_anim.setDuration(400) self._y_anim.setEasingCurve(QEasingCurve.OutSine) self._return_animation.addAnimation(self._x_anim) self._return_animation.addAnimation(self._y_anim) # region Static Functions @staticmethod def constraint(value, min_value, max_value): return min_value if value < min_value else max_value if value > max_value else value # endregion # region Properties def get_x(self): return self._x def set_x(self, x): self._x = self.constraint(x, -1.0, 1.0) radius = (self._bounds.width() - self._knop_bounds.width()) * 0.5 self._knop_bounds.moveCenter( QPointF(self._bounds.center().x() + self._x * radius, self._knop_bounds.center().y())) self.update() self.xChanged.emit(self._x) def get_y(self): return self._y def set_y(self, y): self._y = self.constraint(y, -1.0, 1.0) radius = (self._bounds.width() - self._knop_bounds.width()) * 0.5 self._knop_bounds.moveCenter( QPointF(self._knop_bounds.center().x(), self._bounds.center().y() - self._y * radius)) self.update() self.yChanged.emit(self._x) def get_alignment(self): return self._alignment def set_alignment(self, alignment): self._alignment = alignment x = property(get_x, set_x) y = property(get_y, set_y) alignment = property(get_alignment, set_alignment) # endregion # region Override Functions def resizeEvent(self, event): a = min(self.width(), self.height()) top_left = QPointF() if self._alignment & Qt.AlignTop: top_left.setY(0) elif self._alignment & Qt.AlignVCenter: top_left.setY((self.height() - a) * 0.5) elif self._alignment & Qt.AlignBottom: top_left.setY(self.height() - a) if self._alignment & Qt.AlignLeft: top_left.setX(0) elif self._alignment & Qt.AlignHCenter: top_left.setX((self.width() - a) * 0.5) elif self._alignment & Qt.AlignRight: top_left.setX(self.width() - a) self._bounds = QRectF(top_left, QSize(a, a)) self._knop_bounds.setWidth(a * 0.3) self._knop_bounds.setHeight(a * 0.3) radius = (self._bounds.width() - self._knop_bounds.height()) * 0.5 self._knop_bounds.moveCenter( QPointF(self._bounds.center().x() + self._x * radius, self._bounds.center().y() - self._y * radius)) def mousePressEvent(self, event): if self._knop_bounds.contains(event.pos()): # self._return_animation.stop() self._last_pos = event.pos() self._knop_pressed = True def mouseReleaseEvent(self, event): self._knop_pressed = False self.x = 0.0 self.y = 0.0 # self._return_animation.start() def mouseMoveEvent(self, event): if not self._knop_pressed: return delta_pos = QPointF(event.pos() - self._last_pos) delta_pos += 0.5 * (QPointF(event.pos()) - self._knop_bounds.center()) from_center_to_knop = self._knop_bounds.center( ) + delta_pos - self._bounds.center() radius = (self._bounds.width() - self._knop_bounds.width()) * 0.5 from_center_to_knop.setX( self.constraint(from_center_to_knop.x(), -radius, radius)) from_center_to_knop.setY( self.constraint(from_center_to_knop.y(), -radius, radius)) self._knop_bounds.moveCenter(from_center_to_knop + self._bounds.center()) self._last_pos = event.pos() self.update() if radius == 0: return x = (self._knop_bounds.center().x() - self._bounds.center().x()) / radius y = (-self._knop_bounds.center().y() + self._bounds.center().y()) / radius if self._x != x: self._x = x self.xChanged.emit(self._x) if self._y != y: self._y = y self.yChanged.emit(self._y) def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.HighQualityAntialiasing) gradient = QRadialGradient(self._bounds.center(), self._bounds.width() * 0.5, self._bounds.center()) gradient.setFocalRadius(self._bounds.width() * 0.3) gradient.setCenterRadius(self._bounds.width() * 0.7) gradient.setColorAt(0, Qt.white) gradient.setColorAt(1, Qt.lightGray) painter.setPen(QPen(QBrush(Qt.gray), self._bounds.width() * 0.005)) painter.setBrush(QBrush(gradient)) painter.drawEllipse(self._bounds) painter.setPen(QPen(QBrush(Qt.gray), self._bounds.width() * 0.005)) painter.drawLine( QPointF(self._bounds.left(), self._bounds.center().y()), QPointF(self._bounds.center().x() - self._bounds.width() * 0.35, self._bounds.center().y())) painter.drawLine( QPointF(self._bounds.center().x() + self._bounds.width() * 0.35, self._bounds.center().y()), QPointF(self._bounds.right(), self._bounds.center().y())) painter.drawLine( QPointF(self._bounds.center().x(), self._bounds.top()), QPointF(self._bounds.center().x(), self._bounds.center().y() - self._bounds.width() * 0.35)) painter.drawLine( QPointF(self._bounds.center().x(), self._bounds.center().y() + self._bounds.width() * 0.35), QPointF(self._bounds.center().x(), self._bounds.bottom())) if not self.isEnabled(): return gradient = QRadialGradient(self._knop_bounds.center(), self._knop_bounds.width() * 0.5, self._knop_bounds.center()) gradient.setFocalRadius(self._knop_bounds.width() * 0.2) gradient.setCenterRadius(self._knop_bounds.width() * 0.5) gradient.setColorAt(0, Qt.gray) gradient.setColorAt(1, Qt.darkGray) painter.setPen(QPen(QBrush(Qt.darkGray), self._bounds.width() * 0.005)) painter.setBrush(QBrush(gradient)) painter.drawEllipse(self._knop_bounds) # endregion # region Public Functions def add_x_animation(self): # Abort if the animation is already added if self._x_anim.parent() == self._return_animation: return self._return_animation.addAnimation(self._x_anim) def remove_x_animation(self): # Abort if the animation is already removed if self._x_anim.parent() != self._return_animation: return self._return_animation.removeAnimation(self._x_anim) # Take ownership of the animation (parent is 0 after removeAnimation()) self._x_anim.setParent(self) def add_y_animation(self): # Abort if the animation is already added if self._y_anim.parent() == self._return_animation: return self._return_animation.addAnimation(self._y_anim) def remove_y_animation(self): # Abort if the animation is already removed if self._y_anim.parent() != self._return_animation: return self._return_animation.removeAnimation(self._y_anim) # Take ownership of the animation (parent is 0 after removeAnimation()) self._y_anim.setParent(self)
def render(self, painter: QPainter) -> None: painter.drawText(QRectF(0, 0, self.width(), self.height()), Qt.AlignCenter, "QWindow")
class Callout(QGraphicsItem): def __init__(self, chart): super().__init__(chart) self.m_chart = chart self.m_text = "" self.m_textRect = QRectF() self.m_rect = QRectF() self.m_anchor = QPointF() self.m_font = QFont() def boundingRect(self): anchor = self.mapFromParent(self.m_chart.mapToPosition(self.m_anchor)) rect = QRectF() rect.setLeft(min(self.m_rect.left(), anchor.x())) rect.setRight(max(self.m_rect.right(), anchor.x())) rect.setTop(min(self.m_rect.top(), anchor.y())) rect.setBottom(max(self.m_rect.bottom(), anchor.y())) return rect def paint(self, painter, option, widget=None): path = QPainterPath() path.addRoundedRect(self.m_rect, 5, 5) anchor = self.mapFromParent(self.m_chart.mapToPosition(self.m_anchor)) if not self.m_rect.contains(anchor): point1 = QPointF() point2 = QPointF() # establish the position of the anchor point in relation to m_rect above = anchor.y() <= self.m_rect.top() aboveCenter = (anchor.y() > self.m_rect.top() and anchor.y() <= self.m_rect.center().y()) belowCenter = (anchor.y() > self.m_rect.center().y() and anchor.y() <= self.m_rect.bottom()) below = anchor.y() > self.m_rect.bottom() onLeft = anchor.x() <= self.m_rect.left() leftOfCenter = (anchor.x() > self.m_rect.left() and anchor.x() <= self.m_rect.center().x()) rightOfCenter = (anchor.x() > self.m_rect.center().x() and anchor.x() <= self.m_rect.right()) onRight = anchor.x() > self.m_rect.right() # get the nearest m_rect corner. x = (onRight + rightOfCenter) * self.m_rect.width() y = (below + belowCenter) * self.m_rect.height() cornerCase = ((above and onLeft) or (above and onRight) or (below and onLeft) or (below and onRight)) vertical = abs(anchor.x() - x) > abs(anchor.y() - y) x1 = (x + leftOfCenter * 10 - rightOfCenter * 20 + cornerCase * int(not vertical) * (onLeft * 10 - onRight * 20)) y1 = (y + aboveCenter * 10 - belowCenter * 20 + cornerCase * int(vertical) * (above * 10 - below * 20)) point1.setX(x1) point1.setY(y1) x2 = (x + leftOfCenter * 20 - rightOfCenter * 10 + cornerCase * int(not vertical) * (onLeft * 20 - onRight * 10)) y2 = (y + aboveCenter * 20 - belowCenter * 10 + cornerCase * int(vertical) * (above * 20 - below * 10)) point2.setX(x2) point2.setY(y2) path.moveTo(point1) path.lineTo(anchor) path.lineTo(point2) path = path.simplified() painter.setBrush(QColor(255, 255, 255)) painter.drawPath(path) painter.drawText(self.m_textRect, self.m_text) def mousePressEvent(self, event): event.setAccepted(True) def mouseMoveEvent(self, event): if event.buttons() & Qt.LeftButton: self.setPos( self.mapToParent(event.pos() - event.buttonDownPos(Qt.LeftButton))) event.setAccepted(True) else: event.setAccepted(False) def setText(self, text): self.m_text = text metrics = QFontMetrics(self.m_font) self.m_textRect = QRectF( metrics.boundingRect(QRect(0, 0, 150, 150), Qt.AlignLeft, self.m_text)) self.m_textRect.translate(5, 5) self.prepareGeometryChange() self.m_rect = self.m_textRect.adjusted(-5, -5, 5, 5) def setAnchor(self, point): self.m_anchor = point def updateGeometry(self): self.prepareGeometryChange() self.setPos( self.m_chart.mapToPosition(self.m_anchor) + QPoint(10, -50))
def boundingRect(self): return QRectF(self._bounding_rect or self._rect)
def boundingRect(self): return QRectF(0, 0, 20, 20)
def drawMagnifier(self): # First, calculate the magnifier position due to the mouse position watchAreaWidth = 16 watchAreaHeight = 16 watchAreaPixmap = QPixmap() cursor_pos = self.mousePoint watchArea = QRect( QPoint(cursor_pos.x() - watchAreaWidth / 2, cursor_pos.y() - watchAreaHeight / 2), QPoint(cursor_pos.x() + watchAreaWidth / 2, cursor_pos.y() + watchAreaHeight / 2)) if watchArea.left() < 0: watchArea.moveLeft(0) watchArea.moveRight(watchAreaWidth) if self.mousePoint.x() + watchAreaWidth / 2 >= self.screenPixel.width( ): watchArea.moveRight(self.screenPixel.width() - 1) watchArea.moveLeft(watchArea.right() - watchAreaWidth) if self.mousePoint.y() - watchAreaHeight / 2 < 0: watchArea.moveTop(0) watchArea.moveBottom(watchAreaHeight) if self.mousePoint.y( ) + watchAreaHeight / 2 >= self.screenPixel.height(): watchArea.moveBottom(self.screenPixel.height() - 1) watchArea.moveTop(watchArea.bottom() - watchAreaHeight) # tricks to solve the hidpi impact on QCursor.pos() watchArea.setTopLeft( QPoint(watchArea.topLeft().x() * self.scale, watchArea.topLeft().y() * self.scale)) watchArea.setBottomRight( QPoint(watchArea.bottomRight().x() * self.scale, watchArea.bottomRight().y() * self.scale)) watchAreaPixmap = self.screenPixel.copy(watchArea) # second, calculate the magnifier area magnifierAreaWidth = watchAreaWidth * 10 magnifierAreaHeight = watchAreaHeight * 10 fontAreaHeight = 40 cursorSize = 24 magnifierArea = QRectF( QPoint(QCursor.pos().x() + cursorSize, QCursor.pos().y() + cursorSize), QPoint(QCursor.pos().x() + cursorSize + magnifierAreaWidth, QCursor.pos().y() + cursorSize + magnifierAreaHeight)) if magnifierArea.right() >= self.screenPixel.width(): magnifierArea.moveLeft(QCursor.pos().x() - magnifierAreaWidth - cursorSize / 2) if magnifierArea.bottom() + fontAreaHeight >= self.screenPixel.height( ): magnifierArea.moveTop(QCursor.pos().y() - magnifierAreaHeight - cursorSize / 2 - fontAreaHeight) # third, draw the watch area to magnifier area watchAreaScaled = watchAreaPixmap.scaled( QSize(magnifierAreaWidth * self.scale, magnifierAreaHeight * self.scale)) magnifierPixmap = self.graphicsScene.addPixmap(watchAreaScaled) magnifierPixmap.setOffset(magnifierArea.topLeft()) # then draw lines and text self.graphicsScene.addRect(QRectF(magnifierArea), QPen(QColor(255, 255, 255), 2)) self.graphicsScene.addLine( QLineF(QPointF(magnifierArea.center().x(), magnifierArea.top()), QPointF(magnifierArea.center().x(), magnifierArea.bottom())), QPen(QColor(0, 255, 255), 2)) self.graphicsScene.addLine( QLineF(QPointF(magnifierArea.left(), magnifierArea.center().y()), QPointF(magnifierArea.right(), magnifierArea.center().y())), QPen(QColor(0, 255, 255), 2)) # get the rgb of mouse point pointRgb = QColor(self.screenPixel.toImage().pixel(self.mousePoint)) # draw information self.graphicsScene.addRect( QRectF( magnifierArea.bottomLeft(), magnifierArea.bottomRight() + QPoint(0, fontAreaHeight + 30)), QPen(Qt.black), QBrush(Qt.black)) rgbInfo = self.graphicsScene.addSimpleText( ' Rgb: ({0}, {1}, {2})'.format(pointRgb.red(), pointRgb.green(), pointRgb.blue())) rgbInfo.setPos(magnifierArea.bottomLeft() + QPoint(0, 5)) rgbInfo.setPen(QPen(QColor(255, 255, 255), 2)) rect = self.selectedArea.normalized() sizeInfo = self.graphicsScene.addSimpleText(' Size: {0} x {1}'.format( rect.width() * self.scale, rect.height() * self.scale)) sizeInfo.setPos(magnifierArea.bottomLeft() + QPoint(0, 15) + QPoint(0, fontAreaHeight / 2)) sizeInfo.setPen(QPen(QColor(255, 255, 255), 2))
def boundingRect(self): return QRectF(0, -0.5, self._width, self._height)
class Chip(QGraphicsItem): # Create the bounding rectangle once. BoundingRect = QRectF(0, 0, 110, 70) def __init__(self, color, x=0, y=0): super(Chip, self).__init__() self.color = color self.x = x self.y = y self.stuff = [] self.setZValue((x + y) % 2) self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable) self.setAcceptHoverEvents(True) def boundingRect(self): return Chip.BoundingRect def shape(self): path = QPainterPath() path.addRect(14, 14, 82, 42) return path def paint(self, painter, option, widget): fillColor = self.color if option.state & QStyle.State_Selected: fillColor = self.color.darker(150) if option.state & QStyle.State_MouseOver: fillColor = fillColor.lighter(125) lod = option.levelOfDetailFromTransform(painter.worldTransform()) if lod < 0.2: if lod < 0.125: painter.fillRect(QRectF(0, 0, 110, 70), fillColor) return b = painter.brush() painter.setBrush(fillColor) painter.drawRect(13, 13, 97, 57) painter.setBrush(b) return oldPen = painter.pen() pen = oldPen width = 0 if option.state & QStyle.State_Selected: width += 2 pen.setWidth(width) b = painter.brush() painter.setBrush( QBrush( fillColor.darker(120 if (option.state & QStyle.State_Sunken) else 100))) painter.drawRect(QRect(14, 14, 79, 39)) painter.setBrush(b) if lod >= 1: painter.setPen(QPen(Qt.gray, 1)) painter.drawLine(15, 54, 94, 54) painter.drawLine(94, 53, 94, 15) painter.setPen(QPen(Qt.black, 0)) # Draw text if lod >= 2: font = QFont("Times", 10) font.setStyleStrategy(QFont.ForceOutline) painter.setFont(font) painter.save() painter.scale(0.1, 0.1) painter.drawText( 170, 180, "Model: VSC-2000 (Very Small Chip) at {}x{}".format( self.x, self.y)) painter.drawText(170, 200, "Serial number: DLWR-WEER-123L-ZZ33-SDSJ") painter.drawText(170, 220, "Manufacturer: Chip Manufacturer") painter.restore() # Draw lines lines = [] # QVarLengthArray < QLineF, 36 > if lod >= 0.5: for i in range( 0, 11, 1 if lod > 0.5 else 2): # (int i = 0 i <= 10 i += (1 if lod > 0.5 else 2)): lines.append(QLineF(18 + 7 * i, 13, 18 + 7 * i, 5)) lines.append(QLineF(18 + 7 * i, 54, 18 + 7 * i, 62)) for i in range(0, 6, 1 if lod > 0.5 else 2): # (int i = 0 i <= 6 i += (lod > 0.5 ? 1: 2)) { lines.append(QLineF(5, 18 + i * 5, 13, 18 + i * 5)) lines.append(QLineF(94, 18 + i * 5, 102, 18 + i * 5)) if lod >= 0.4: lineData = [ QLineF(25, 35, 35, 35), QLineF(35, 30, 35, 40), QLineF(35, 30, 45, 35), QLineF(35, 40, 45, 35), QLineF(45, 30, 45, 40), QLineF(45, 35, 55, 35) ] lines.extend(lineData) painter.drawLines(lines) # Draw red ink if len(self.stuff) > 1: p = painter.pen() painter.setPen( QPen(Qt.red, 1, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.setBrush(Qt.NoBrush) path = QPainterPath path.moveTo(self.stuff[0]) for i in range(1, len(self.stuff)): path.lineTo(self.stuff[i]) painter.drawPath(path) painter.setPen(p) """ # Body. painter.setBrush(self.color) painter.drawEllipse(-10, -20, 20, 40) # Eyes. painter.setBrush(Qt.white) painter.drawEllipse(-10, -17, 8, 8) painter.drawEllipse(2, -17, 8, 8) # Nose. painter.setBrush(Qt.black) painter.drawEllipse(QRectF(-2, -22, 4, 4)) # Pupils. painter.drawEllipse(QRectF(-8.0 + self.mouseEyeDirection, -17, 4, 4)) painter.drawEllipse(QRectF(4.0 + self.mouseEyeDirection, -17, 4, 4)) # Ears. if self.scene().collidingItems(self): painter.setBrush(Qt.red) else: painter.setBrush(Qt.darkYellow) painter.drawEllipse(-17, -12, 16, 16) painter.drawEllipse(1, -12, 16, 16) # Tail. path = QPainterPath(QPointF(0, 20)) path.cubicTo(-5, 22, -5, 22, 0, 25) path.cubicTo(5, 27, 5, 32, 0, 30) path.cubicTo(-5, 32, -5, 42, 0, 35) painter.setBrush(Qt.NoBrush) painter.drawPath(path) """ def mousePressEvent(self, event): super(Chip, self).mousePressEvent(event) self.update() def mouseMoveEvent(self, event): if event.modifiers() & Qt.ShiftModifier: self.stuff.append(event.pos()) self.update() return super(Chip, self).mouseMoveEvent(event) def mouseReleaseEvent(self, event): super(Chip, self).mouseReleaseEvent(event) self.update()
def drawOneStep(self, step): """ :type step: tuple """ if step[0] == ACTION_RECT: self.graphicsScene.addRect( QRectF(QPointF(step[1], step[2]), QPointF(step[3], step[4])), step[5]) elif step[0] == ACTION_ELLIPSE: self.graphicsScene.addEllipse( QRectF(QPointF(step[1], step[2]), QPointF(step[3], step[4])), step[5]) elif step[0] == ACTION_ARROW: arrow = QPolygonF() linex = float(step[1] - step[3]) liney = float(step[2] - step[4]) line = sqrt(pow(linex, 2) + pow(liney, 2)) # in case to divided by 0 if line == 0: return sinAngel = liney / line cosAngel = linex / line # sideLength is the length of bottom side of the body of an arrow # arrowSize is the size of the head of an arrow, left and right # sides' size is arrowSize, and the bottom side's size is arrowSize / 2 sideLength = step[5].width() arrowSize = 8 bottomSize = arrowSize / 2 tmpPoint = QPointF(step[3] + arrowSize * sideLength * cosAngel, step[4] + arrowSize * sideLength * sinAngel) point1 = QPointF(step[1] + sideLength * sinAngel, step[2] - sideLength * cosAngel) point2 = QPointF(step[1] - sideLength * sinAngel, step[2] + sideLength * cosAngel) point3 = QPointF(tmpPoint.x() - sideLength * sinAngel, tmpPoint.y() + sideLength * cosAngel) point4 = QPointF(tmpPoint.x() - bottomSize * sideLength * sinAngel, tmpPoint.y() + bottomSize * sideLength * cosAngel) point5 = QPointF(step[3], step[4]) point6 = QPointF(tmpPoint.x() + bottomSize * sideLength * sinAngel, tmpPoint.y() - bottomSize * sideLength * cosAngel) point7 = QPointF(tmpPoint.x() + sideLength * sinAngel, tmpPoint.y() - sideLength * cosAngel) arrow.append(point1) arrow.append(point2) arrow.append(point3) arrow.append(point4) arrow.append(point5) arrow.append(point6) arrow.append(point7) arrow.append(point1) self.graphicsScene.addPolygon(arrow, step[5], step[6]) elif step[0] == ACTION_LINE: self.graphicsScene.addLine( QLineF(QPointF(step[1], step[2]), QPointF(step[3], step[4])), step[5]) elif step[0] == ACTION_FREEPEN: self.graphicsScene.addPath(step[1], step[2]) elif step[0] == ACTION_TEXT: textAdd = self.graphicsScene.addSimpleText(step[1], step[2]) textAdd.setPos(step[3]) textAdd.setBrush(QBrush(step[4])) self.textRect = textAdd.boundingRect()