def paint(self, painter): widget = self.parent() scale = widget.inverseScale() # metrics if self._rulerObject is not None: line, d, a = self._rulerObject origin = line.p1() cursor = line.p2() sz = 8 * scale color = QColor(140, 193, 255, 170) # line painter.save() painter.setPen(color) drawing.drawLine(painter, origin.x(), origin.y(), cursor.x(), cursor.y(), scale) path = QPainterPath() path.addEllipse(origin.x() - sz / 2, origin.y() - sz / 2, sz, sz) path.addEllipse(cursor.x() - sz / 2, cursor.y() - sz / 2, sz, sz) painter.fillPath(path, color) painter.restore() # text xAlign = yAlign = "center" pos = (origin + cursor) / 2 drawing.drawTextAtPoint(painter, d, pos.x(), pos.y(), scale, xAlign, yAlign) xAlign, yAlign = "left", "top" dx = cursor.x() - origin.x() if dx < 0: xAlign = "right" drawing.drawTextAtPoint(painter, a, cursor.x(), cursor.y(), scale, xAlign, yAlign)
def paintEvent(self, event): # Draw backgrounds according to css styleOpt = QStyleOption() styleOpt.initFrom(self) p = QPainter(self) p.setRenderHint(QPainter.Antialiasing) self.style().drawPrimitive(QStyle.PE_Widget, styleOpt, p, self) if self.values == None or len(self.values) == 0: return # print(len(self.values)) r = self.rect() dx = r.width() / float(self.datapoints - 1) # Build a path from the readings path = QPainterPath() path.moveTo(r.bottomRight()) i = 0 for reading in reversed(self.values): pt = QPointF(r.width() - i*dx, (1.0 - reading) * r.height()) path.lineTo(pt) i = i + 1 path.lineTo(path.currentPosition().x(), r.height()) path.closeSubpath() # Use foreground color for graph gcolor = styleOpt.palette.color(QPalette.Text) p.setBrush(gcolor) p.setPen(gcolor) p.drawPath(path)
def orbit(self): """Return a QPainterPath that shows the beam orbit.""" a, b = self.endpoints() path = QPainterPath() path.moveTo(*a) path.lineTo(*b) return path
def painterPath(self): rect = self._rect radius = self._RADIUS path = QPainterPath() path.addRoundedRect(rect, radius, radius) return path
def set_shape(self, width, height): ''' Define the bouding rectangle of the JOIN symbol ''' circ = min(width, height) path = QPainterPath() path.addEllipse(0, 0, circ, circ) self.setPath(path) super(Join, self).set_shape(width, height)
def addPort(self, name, isOutput = False, flags = 0, ptr = None): port = QNEPort(self) port.setName(name) port.setIsOutput(isOutput) port.setNEBlock(self) port.setPortFlags(flags) port.setPtr(ptr) fontmetrics = QFontMetrics(self.scene().font()); width = fontmetrics.width(name) height = fontmetrics.height() if width > self.width - self.horzMargin: self.width = width + self.horzMargin self.height += height path = QPainterPath() path.addRoundedRect(-self.width/2, -self.height/2, self.width, self.height, 5, 5) self.setPath(path) y = -self.height / 2 + self.vertMargin + port.radius() for port_ in self.childItems(): if port_.type() != QNEPort.Type: continue if port_.isOutput(): port_.setPos(self.width/2 + port.radius(), y) else: port_.setPos(-self.width/2 - port.radius(), y) y += height; return port
def updateAngle(self, startAngle, spanAngle): self._startAngle = startAngle self._spanAngle = spanAngle path = QPainterPath() path.arcMoveTo(self._parent._rect, startAngle) path.arcTo(self._parent._rect, startAngle, spanAngle) self.setPath(path)
def draw_connection_line(self, painter, x1, y1, x2, y2, h1, h2): # Account for list view headers. y1 += h1 y2 += h2 # Invisible output ports don't get a connecting dot. if y1 > h1: painter.drawLine(x1, y1, x1 + 4, y1) # Setup control points spline = QPolygon(4) cp = int((x2 - x1 - 8) * 0.4) spline.setPoints(x1 + 4, y1, x1 + 4 + cp, y1, x2 - 4 - cp, y2, x2 - 4, y2) # The connection line path = QPainterPath() path.moveTo(spline.at(0)) path.cubicTo(spline.at(1), spline.at(2), spline.at(3)) painter.strokePath(path, painter.pen()) # painter.drawLine(x1 + 4, y1, x2 - 4, y2) # Invisible input ports don't get a connecting dot. if y2 > h2: painter.drawLine(x2 - 4, y2, x2, y2)
def _get_pos_widget(name, backgroundColor, foregroundColor): label = QLabel() label.setAttribute(Qt.WA_TransparentForMouseEvents, True) pixmap = QPixmap(25 * 10, 25 * 10) pixmap.fill(backgroundColor) painter = QPainter() painter.begin(pixmap) pen = QPen(foregroundColor) painter.setPen(pen) painter.setRenderHint(QPainter.Antialiasing) font = QFont() font.setBold(True) font.setPixelSize(25 * 10 - 30) path = QPainterPath() path.addText(QPointF(50, 25 * 10 - 50), font, name) brush = QBrush(foregroundColor) painter.setBrush(brush) painter.drawPath(path) painter.setFont(font) painter.end() pixmap = pixmap.scaled(QSize(20, 20), Qt.KeepAspectRatio, Qt.SmoothTransformation) label.setPixmap(pixmap) spinbox = DelayedSpinBox(750) spinbox.setAlignment(Qt.AlignCenter) spinbox.setToolTip("{0} Spin Box".format(name)) spinbox.setButtonSymbols(QAbstractSpinBox.NoButtons) spinbox.setMaximumHeight(20) font = spinbox.font() font.setPixelSize(14) spinbox.setFont(font) sheet = TEMPLATE.format(foregroundColor.name(), backgroundColor.name()) spinbox.setStyleSheet(sheet) return label, spinbox
def drawGlyphAnchors(painter, glyph, scale, rect, drawAnchors=True, drawText=True, color=None): if not glyph.anchors: return if color is None: color = defaultColor("glyphAnchor") fallbackColor = color anchorSize = 6 * scale anchorHalfSize = anchorSize / 2 for anchor in glyph.anchors: if anchor.color is not None: color = colorToQColor(anchor.color) else: color = fallbackColor x = anchor.x y = anchor.y name = anchor.name painter.save() # XXX: put gfx form to selected anchors if drawAnchors: path = QPainterPath() path.addEllipse(x - anchorHalfSize, y - anchorHalfSize, anchorSize, anchorSize) painter.fillPath(path, color) if drawText and name: painter.setPen(color) # TODO: we're using + before we shift to top, ideally this should # be abstracted w drawTextAtPoint taking a dy parameter that will # offset the drawing region from origin regardless of whether we # are aligning to top or bottom. y += 3 * scale drawTextAtPoint(painter, name, x, y, scale, xAlign="center", yAlign="top") painter.restore()
def paintEvent(self, event): # Check whether this orb is enhanced if type(self.parent) == Board: enh = self.parent.enhanced[self.position] else: enh = False painter = QPainter(self) painter.drawPixmap(event.rect().adjusted(2,2,-2,-2), self.pixmap()) w = event.rect().width() if enh: path = QPainterPath() pen = QPen() pen.setWidth(1); pen.setBrush(Qt.white) brush = QBrush(Qt.yellow) font = QFont() font.setPointSize(20) font.setWeight(QFont.Black) path.addText(event.rect().x()+w-15,event.rect().y()+w-5,font,'+') painter.setPen(pen) painter.setBrush(brush) painter.setFont(font) painter.drawPath(path)
def painterPath(self): """ Returns the current shape as QPainterPath (used for collision detection). :rtype: QPainterPath """ path = QPainterPath() path.addRect(self.polygon) return path
def shape(self): """ Returns the shape of this item as a QPainterPath in local coordinates. :rtype: QPainterPath """ path = QPainterPath() path.addPolygon(self.polygon) return path
def shape(self): """ Returns the shape of this item as a QPainterPath in local coordinates. :rtype: QPainterPath """ path = QPainterPath() path.addRect(self.boundingRect()) return path
def __init__(self, pos, edge, symbol): ''' Create the point - as a small, lightblue box ''' super(Connectionpoint, self).__init__(pos, edge=edge) path = QPainterPath() path.addRect(0, 0, 10, 10) self.setPath(path) self.setPos(pos.x() - 5, pos.y() - 5) # Symbol actually owning the connection point self.symbol = symbol
def shape(self): """ Returns the shape of this item as a QPainterPath in local coordinates. :rtype: QPainterPath """ path = QPainterPath() path.addRect(self.polygon) for shape in self.handleBound: path.addEllipse(shape) return path
def shape(self): """ Returns the shape of this item as a QPainterPath in local coordinates. """ path = QPainterPath() path.addRect(self.rect()) if self.isSelected(): for shape in self.handles.values(): path.addEllipse(shape) return path
def painterPath(self): """ Returns the current shape as QPainterPath (used for collision detection). :rtype: QPainterPath """ path = QPainterPath() path.addPath(self.path) path.addPolygon(self.head) path.addPolygon(self.tail) return path
def doHoneycomb(self, part_item, radius, bounds): """Summary Args: part_item (TYPE): Description radius (TYPE): Description bounds (TYPE): Description Returns: TYPE: Description """ doLattice = HoneycombDnaPart.latticeCoordToPositionXY doPosition = HoneycombDnaPart.positionToLatticeCoordRound isEven = HoneycombDnaPart.isEvenParity x_l, x_h, y_l, y_h = bounds dot_size, half_dot_size = self.dots sf = part_item.scale_factor points = self.points row_l, col_l = doPosition(radius, x_l, -y_l, False, False, scale_factor=sf) row_h, col_h = doPosition(radius, x_h, -y_h, True, True, scale_factor=sf) # print(row_l, row_h, col_l, col_h) path = QPainterPath() is_pen_down = False draw_lines = self.draw_lines for i in range(row_l, row_h): for j in range(col_l, col_h+1): x, y = doLattice(radius, i, j, scale_factor=sf) if draw_lines: if is_pen_down: path.lineTo(x, -y) else: is_pen_down = True path.moveTo(x, -y) """ +x is Left and +y is down origin of ellipse is Top Left corner so we subtract half in X and subtract in y """ pt = GridPoint(x - half_dot_size, -y - half_dot_size, dot_size, self) pt.setPen(getPenObj(Qt.blue, 1.0)) points.append(pt) is_pen_down = False # end for i # DO VERTICAL LINES if draw_lines: for j in range(col_l, col_h+1): # print("newcol") for i in range(row_l, row_h): x, y = doLattice(radius, i, j, scale_factor=sf) if is_pen_down and isEven(i, j): path.lineTo(x, -y) is_pen_down = False else: is_pen_down = True path.moveTo(x, -y) is_pen_down = False # end for j self.setPath(path)
def __init__(self, pos, edge): ''' Set the original control point - with color, shape ''' path = QPainterPath() path.addEllipse(pos.x() - 5, pos.y() - 5, 10, 10) super(Controlpoint, self).__init__(path, parent=edge) self.setPen(QColor(50, 100, 120, 200)) self.setBrush(QColor(200, 200, 210, 120)) self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable) self.edge = edge self.hide()
def set_shape(self, width, height): ''' Compute the polygon to fit in width, height ''' self.setPen(QPen(Qt.blue)) self.textbox_alignment = Qt.AlignLeft | Qt.AlignTop path = QPainterPath() path.moveTo(0, 0) path.lineTo(0, height) #path.moveTo(0, height / 2) #path.lineTo(width, height / 2) self.setPath(path) super(Input, self).set_shape(width, height)
def paint_to(self, painter): if len(self.points) > 1: painter.setPen(Qt.red) paint_path = QPainterPath() paint_path.moveTo(*self.points[0][0]) for pos, _ in self.points[1:]: paint_path.lineTo(*pos) painter.drawPath(paint_path) painter.setPen(Qt.green) for pos, _ in self.points: painter.drawPoint(*pos)
def set_shape(self, width, height): ''' Compute the polygon to fit in width, height ''' path = QPainterPath() path.addRoundedRect(0, 0, width, height, height / 4, height) if self.nested_scene and self.is_composite(): # Distinguish composite states with dash line self.setPen(QPen(Qt.DashLine)) else: self.setPen(QPen(Qt.SolidLine)) self.setPath(path) super(State, self).set_shape(width, height)
def lozengePath(x, y, size): halfSize = size / 2 path = QPainterPath() path.moveTo(x - halfSize, y) path.lineTo(x, y + halfSize) path.lineTo(x + halfSize, y) path.lineTo(x, y - halfSize) path.closeSubpath() return path
def _updateSequenceText(self): seq_item = self._seq_item is_on_top = self._is_on_top index = self._insertion.idx() base_text = self._seq_text font = styles.SEQUENCEFONT seq_font_h = styles.SEQUENCEFONTH insert_w = styles.INSERTWIDTH seq_font_char_w = styles.SEQUENCEFONTCHARWIDTH # draw sequence on the insert if base_text: # only draw sequences if they exist i.e. not None! len_BT = len(base_text) if is_on_top: angle_offset = 0 else: angle_offset = 180 if len_BT > 20: base_text = base_text[:17] + '...' len_BT = len(base_text) fraction_arc_len_per_char = (1.0 - 2.0*_FRACTION_INSERT_TO_PAD) / (len_BT + 1) seq_item.setPen(QPen(Qt.NoPen)) seq_item.setBrush(QBrush(Qt.black)) seq_path = QPainterPath() loop_path = self.path() for i in range(len_BT): frac = _FRACTION_INSERT_TO_PAD + (i+1)*fraction_arc_len_per_char pt = loop_path.pointAtPercent(frac) tang_ang = loop_path.angleAtPercent(frac) temp_path = QPainterPath() # 1. draw the text temp_path.addText(0, 0, font, base_text[i if is_on_top else -i-1]) # 2. center it at the zero point different for top and bottom # strands if not is_on_top: temp_path.translate(0, -seq_font_h - insert_w) temp_path.translate(QPointF(-seq_font_char_w / 2., -2 if is_on_top else seq_font_h)) mat = QTransform() # 3. rotate it mat.rotate(-tang_ang + angle_offset) rotated_path = mat.map(temp_path) # 4. translate the rotate object to it's position on the part rotated_path.translate(pt) seq_path.addPath(rotated_path) # end for seq_item.setPath(seq_path)
def set_shape(self, width, height): ''' Compute the polygon to fit in width, height ''' path = QPainterPath() path.lineTo(width, 0) path.lineTo(width, height) path.lineTo(0, height) path.lineTo(0, 0) self.setPath(path) super(Task, self).set_shape(width, height)
def set_shape(self, width, height): ''' Define polygon points to draw the symbol ''' path = QPainterPath() path.moveTo(width / 2, 0) path.lineTo(width, height / 2) path.lineTo(width / 2, height) path.lineTo(0, height / 2) path.lineTo(width / 2, 0) self.setPath(path) super(Decision, self).set_shape(width, height)
def mousePressEvent(self, event): pos = self.magnetPos(event.localPos()) x, y = pos.x(), pos.y() path = QPainterPath() path.moveTo(x, y) path.lineTo(x + 1, y) path.lineTo(x + 1, y + 1) path.closeSubpath() text = "0" self._rulerObject = (path, text)
def itemRegion(self, index): if not index.isValid(): return QRegion() if index.column() != 1: return QRegion(self.itemRect(index)) if self.model().data(index) <= 0.0: return QRegion() startAngle = 0.0 for row in range(self.model().rowCount(self.rootIndex())): sliceIndex = self.model().index(row, 1, self.rootIndex()) value = self.model().data(sliceIndex) if value > 0.0: angle = 360*value/self.totalValue if sliceIndex == index: slicePath = QPainterPath() slicePath.moveTo(self.totalSize/2, self.totalSize/2) slicePath.arcTo(self.margin, self.margin, self.margin+self.pieSize, self.margin+self.pieSize, startAngle, angle) slicePath.closeSubpath() return QRegion(slicePath.toFillPolygon().toPolygon()) startAngle += angle return QRegion()
def _drawTextShadow(self, painter: QPainter, x: int, y: int, text: str): font = self.font() # setup outline path text_path = QPainterPath() text_path.addText(x, y, font, text) # draw outline path 1 painter.setPen(self.outline_pen) painter.setBrush(self.outline_brush) painter.drawPath(text_path) # draw text painter.setPen(self.text_color) painter.setFont(font) # Note: The y-position is used as the baseline of the font. painter.drawText(x, y, text)
from . import slicestyles as styles PXI_PP_ITEM_WIDTH = IW = 2.0 # 1.5 TRIANGLE = QPolygonF() TRIANGLE.append(QPointF(0, 0)) TRIANGLE.append(QPointF(0.75*IW, 0.5*IW)) TRIANGLE.append(QPointF(0, IW)) TRIANGLE.append(QPointF(0, 0)) # TRIANGLE.translate(-0.75*IW, -0.5*IW) TRIANGLE.translate(-0.25*IW, -0.5*IW) PXI_RECT = QRectF(0, 0, IW, IW) T90, T270 = QTransform(), QTransform() T90.rotate(90) T270.rotate(270) FWDPXI_PP, REVPXI_PP = QPainterPath(), QPainterPath() FWDPXI_PP.addPolygon(T90.map(TRIANGLE)) REVPXI_PP.addPolygon(T270.map(TRIANGLE)) # FWDPXI_PP.moveTo(-0.5*IW, 0.7*IW) # FWDPXI_PP.lineTo(0., -0.2*IW) # FWDPXI_PP.lineTo(0.5*IW, 0.7*IW) # extra1 = QPainterPath() # extra1.addEllipse(-0.5*IW, 0.5*IW, IW, 0.4*IW) # extra2 = QPainterPath() # extra2.addEllipse(-0.35*IW, 0.5*IW, 0.7*IW, 0.3*IW) # FWDPXI_PP += extra1 # FWDPXI_PP -= extra2 # REVPXI_PP.moveTo(-0.5*IW, -0.7*IW) # REVPXI_PP.lineTo(0., 0.2*IW)
def createGraphics(self): """ Create the graphical representation of the FMU's inputs and outputs """ def variableColor(variable): if variable.type == 'Real': return QColor.fromRgb(0, 0, 127) elif variable.type in ['Integer', 'Enumeration']: return QColor.fromRgb(255, 127, 0) elif variable.type == 'Boolean': return QColor.fromRgb(255, 0, 255) elif variable.type == 'String': return QColor.fromRgb(0, 128, 0) else: return QColor.fromRgb(0, 0, 0) inputVariables = [] outputVariables = [] maxInputLabelWidth = 0 maxOutputLabelWidth = 0 textItem = QGraphicsTextItem() fontMetrics = QFontMetricsF(textItem.font()) for variable in self.modelDescription.modelVariables: if variable.causality == 'input': inputVariables.append(variable) elif variable.causality == 'output': outputVariables.append(variable) for variable in inputVariables: maxInputLabelWidth = max(maxInputLabelWidth, fontMetrics.width(variable.name)) for variable in outputVariables: maxOutputLabelWidth = max(maxOutputLabelWidth, fontMetrics.width(variable.name)) from math import floor scene = QGraphicsScene() self.ui.graphicsView.setScene(scene) group = QGraphicsItemGroup() scene.addItem(group) group.setPos(200.5, -50.5) lh = 15 # line height w = max(150., maxInputLabelWidth + maxOutputLabelWidth + 20) h = max(50., 10 + lh * max(len(inputVariables), len(outputVariables))) block = QGraphicsRectItem(0, 0, w, h, group) block.setPen(QColor.fromRgb(0, 0, 255)) pen = QPen() pen.setWidthF(1) font = QFont() font.setPixelSize(10) # inputs y = floor((h - len(inputVariables) * lh) / 2 - 2) for variable in inputVariables: text = QGraphicsTextItem(variable.name, group) text.setDefaultTextColor(QColor.fromRgb(0, 0, 255)) text.setFont(font) text.setX(3) text.setY(y) polygon = QPolygonF([QPointF(-13.5, y + 4), QPointF(1, y + 11), QPointF(-13.5, y + 18)]) path = QPainterPath() path.addPolygon(polygon) path.closeSubpath() contour = QGraphicsPathItem(path, group) contour.setPen(QPen(Qt.NoPen)) contour.setBrush(variableColor(variable)) y += lh # outputs y = floor((h - len(outputVariables) * lh) / 2 - 2) for variable in outputVariables: text = QGraphicsTextItem(variable.name, group) text.setDefaultTextColor(QColor.fromRgb(0, 0, 255)) text.setFont(font) text.setX(w - 3 - text.boundingRect().width()) text.setY(y) polygon = QPolygonF([QPointF(w, y + 0 + 7.5), QPointF(w + 7, y + 3.5 + 7.5), QPointF(w, y + 7 + 7.5)]) path = QPainterPath() path.addPolygon(polygon) path.closeSubpath() contour = QGraphicsPathItem(path, group) pen = QPen() pen.setColor(variableColor(variable)) pen.setJoinStyle(Qt.MiterJoin) contour.setPen(pen) y += lh
def shape(self): '''用来进行碰撞检测,这里对于QPP添加一个范围为Head.Rect的圆来定义Path''' # 如果两个头部的矩形交叉,但头部椭圆没有碰撞,则不会检测到碰撞 path = QPainterPath() path.addEllipse(Head.Rect) return path
def paintEvent(self, event): super(WaterWidget, self).paintEvent(event) if self.minimum >= self.maximum: return if not self._updateTimer.isActive(): return # 正弦曲线公式 y = A * sin(ωx + φ) + k # 当前值所占百分比 percent = 1 - (self._value - self.minimum) / \ (self.maximum - self.minimum) # w表示周期,6为人为定义 w = 6 * self.waterDensity * math.pi / self.width() # A振幅 高度百分比,1/26为人为定义 A = self.height() * self.waterHeight * 1 / 26 # k 高度百分比 k = self.height() * percent # 波浪1 waterPath1 = QPainterPath() waterPath1.moveTo(0, self.height()) # 起点在左下角 # 波浪2 waterPath2 = QPainterPath() waterPath2.moveTo(0, self.height()) # 起点在左下角 # 偏移 self._offset += 0.6 if self._offset > self.width() / 2: self._offset = 0 for i in range(self.width() + 1): # 从x轴开始计算y轴点 y = A * math.sin(w * i + self._offset) + k waterPath1.lineTo(i, y) # 相对第一条需要进行错位 y = A * math.sin(w * i + self._offset + self.width() / 2 * A) + k waterPath2.lineTo(i, y) # 封闭两条波浪,形成一个 U形 上面加波浪的封闭区间 waterPath1.lineTo(self.width(), self.height()) waterPath1.lineTo(0, self.height()) waterPath2.lineTo(self.width(), self.height()) waterPath2.lineTo(0, self.height()) # 开始画路径 painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing, True) painter.setRenderHint(QPainter.SmoothPixmapTransform, True) # 设置没有画笔 painter.setPen(Qt.NoPen) # 波浪1 painter.save() painter.setBrush(self._waterBgColor) painter.drawPath(waterPath1) painter.restore() # 波浪2 painter.save() painter.setBrush(self._waterFgColor) painter.drawPath(waterPath2) painter.restore()
def paintEvent(self, event): painter = QPainter(self) event.accept() painter.save() painter.setRenderHint(QPainter.Antialiasing, True) if self.fLabel: if self.fCustomPaintMode == self.CUSTOM_PAINT_MODE_NULL: painter.setPen(self.fLabelGradientColor2) painter.setBrush(self.fLabelGradient) painter.drawRect(self.fLabelGradientRect) painter.setFont(self.fLabelFont) painter.setPen( self.fLabelGradientColorT[0 if self.isEnabled() else 1]) painter.drawText(self.fLabelPos, self.fLabel) if self.isEnabled(): normValue = float(self.fRealValue - self.fMinimum) / float(self.fMaximum - self.fMinimum) target = QRectF(0.0, 0.0, self.fPixmapBaseSize, self.fPixmapBaseSize) curLayer = int((self.fPixmapLayersCount - 1) * normValue) if self.fPixmapOrientation == self.HORIZONTAL: xpos = self.fPixmapBaseSize * curLayer ypos = 0.0 else: xpos = 0.0 ypos = self.fPixmapBaseSize * curLayer source = QRectF(xpos, ypos, self.fPixmapBaseSize, self.fPixmapBaseSize) painter.drawPixmap(target, self.fPixmap, source) # Custom knobs (Dry/Wet and Volume) if self.fCustomPaintMode in (self.CUSTOM_PAINT_MODE_CARLA_WET, self.CUSTOM_PAINT_MODE_CARLA_VOL): # knob color colorGreen = QColor(0x5D, 0xE7, 0x3D).lighter(100 + self.fHoverStep * 6) colorBlue = QColor(0x3E, 0xB8, 0xBE).lighter(100 + self.fHoverStep * 6) # draw small circle ballRect = QRectF(8.0, 8.0, 15.0, 15.0) ballPath = QPainterPath() ballPath.addEllipse(ballRect) #painter.drawRect(ballRect) tmpValue = (0.375 + 0.75 * normValue) ballValue = tmpValue - floor(tmpValue) ballPoint = ballPath.pointAtPercent(ballValue) # draw arc startAngle = 216 * 16 spanAngle = -252 * 16 * normValue if self.fCustomPaintMode == self.CUSTOM_PAINT_MODE_CARLA_WET: painter.setBrush(colorBlue) painter.setPen(QPen(colorBlue, 0)) painter.drawEllipse( QRectF(ballPoint.x(), ballPoint.y(), 2.2, 2.2)) gradient = QConicalGradient(15.5, 15.5, -45) gradient.setColorAt(0.0, colorBlue) gradient.setColorAt(0.125, colorBlue) gradient.setColorAt(0.625, colorGreen) gradient.setColorAt(0.75, colorGreen) gradient.setColorAt(0.76, colorGreen) gradient.setColorAt(1.0, colorGreen) painter.setBrush(gradient) painter.setPen(QPen(gradient, 3)) else: painter.setBrush(colorBlue) painter.setPen(QPen(colorBlue, 0)) painter.drawEllipse( QRectF(ballPoint.x(), ballPoint.y(), 2.2, 2.2)) painter.setBrush(colorBlue) painter.setPen(QPen(colorBlue, 3)) painter.drawArc(4.0, 4.0, 26.0, 26.0, startAngle, spanAngle) # Custom knobs (L and R) elif self.fCustomPaintMode in (self.CUSTOM_PAINT_MODE_CARLA_L, self.CUSTOM_PAINT_MODE_CARLA_R): # knob color color = QColor(0xAD, 0xD5, 0x48).lighter(100 + self.fHoverStep * 6) # draw small circle ballRect = QRectF(7.0, 8.0, 11.0, 12.0) ballPath = QPainterPath() ballPath.addEllipse(ballRect) #painter.drawRect(ballRect) tmpValue = (0.375 + 0.75 * normValue) ballValue = tmpValue - floor(tmpValue) ballPoint = ballPath.pointAtPercent(ballValue) painter.setBrush(color) painter.setPen(QPen(color, 0)) painter.drawEllipse( QRectF(ballPoint.x(), ballPoint.y(), 2.0, 2.0)) # draw arc if self.fCustomPaintMode == self.CUSTOM_PAINT_MODE_CARLA_L: startAngle = 216 * 16 spanAngle = -252.0 * 16 * normValue else: startAngle = 324.0 * 16 spanAngle = 252.0 * 16 * (1.0 - normValue) painter.setPen(QPen(color, 2)) painter.drawArc(3.5, 4.5, 22.0, 22.0, startAngle, spanAngle) # Custom knobs (Color) elif self.fCustomPaintMode == self.CUSTOM_PAINT_MODE_COLOR: # knob color color = self.fCustomPaintColor.lighter(100 + self.fHoverStep * 6) # draw small circle ballRect = QRectF(8.0, 8.0, 15.0, 15.0) ballPath = QPainterPath() ballPath.addEllipse(ballRect) tmpValue = (0.375 + 0.75 * normValue) ballValue = tmpValue - floor(tmpValue) ballPoint = ballPath.pointAtPercent(ballValue) # draw arc startAngle = 216 * 16 spanAngle = -252 * 16 * normValue painter.setBrush(color) painter.setPen(QPen(color, 0)) painter.drawEllipse( QRectF(ballPoint.x(), ballPoint.y(), 2.2, 2.2)) painter.setBrush(color) painter.setPen(QPen(color, 3)) painter.drawArc(4.0, 4.0, 26.0, 26.0, startAngle, spanAngle) # Custom knobs (Zita) elif self.fCustomPaintMode == self.CUSTOM_PAINT_MODE_ZITA: a = normValue * pi * 1.5 - 2.35 r = 10.0 x = 10.5 y = 10.5 x += r * sin(a) y -= r * cos(a) painter.setBrush(Qt.black) painter.setPen(QPen(Qt.black, 2)) painter.drawLine(QPointF(11.0, 11.0), QPointF(x, y)) # Custom knobs else: painter.restore() return if self.HOVER_MIN < self.fHoverStep < self.HOVER_MAX: self.fHoverStep += 1 if self.fIsHovered else -1 QTimer.singleShot(20, self.update) else: # isEnabled() target = QRectF(0.0, 0.0, self.fPixmapBaseSize, self.fPixmapBaseSize) painter.drawPixmap(target, self.fPixmap, target) painter.restore()
def drawGrid(self): ''' Draw the grid for the drawing area ''' # Add vertical minor grids path = QPainterPath() minLoc = self.xMinGrid + self.minorGrid maxLoc = self.xMaxGrid gStep = self.minorGrid for i in range(minLoc, maxLoc, gStep): path.moveTo(i, self.yMinGrid) path.lineTo(i, self.yMaxGrid) self.addPath(path, self.minorGridPen) # Add horizontal minor grids path = QPainterPath() for i in range(minLoc, maxLoc, gStep): path.moveTo(self.xMinGrid, i) path.lineTo(self.xMaxGrid, i) self.addPath(path, self.minorGridPen) # Add vertical minor grids path = QPainterPath() minLoc = self.xMinGrid maxLoc = self.xMaxGrid gStep = self.majorGrid for i in range(minLoc, maxLoc, gStep): path.moveTo(i, self.yMinGrid) path.lineTo(i, self.yMaxGrid) self.addPath(path, self.majorGridPen) # Add vertical minor grids path = QPainterPath() for i in range(minLoc, maxLoc, gStep): path.moveTo(self.xMinGrid, i) path.lineTo(self.xMaxGrid, i) self.addPath(path, self.majorGridPen)
class Grabber(QGraphicsPathItem): """ Extends QGraphicsPathItem to create grabber for line for moving a particular segment """ circle = QPainterPath() circle.addEllipse(QRectF(-5, -5, 10, 10)) def __init__(self, annotation_line, index, direction): super(Grabber, self).__init__() # store line to which it connects self.m_annotation_item = annotation_line # index of first point of segment of above line self.m_index = index self.direction = direction self.setPath(Grabber.circle) # set graphical settings for this item self.setFlag(QGraphicsItem.ItemIsSelectable, True) self.setFlag(QGraphicsItem.ItemIsMovable, True) self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True) self.setAcceptHoverEvents(True) # initially make invisible self.pen = QPen(Qt.white, -1, Qt.SolidLine) self.brush = QBrush(Qt.transparent) def itemChange(self, change, value): """ move position of grabber after resize""" if change == QGraphicsItem.ItemPositionChange and self.isEnabled(): p = QPointF(self.pos()) if self.direction == Qt.Horizontal: p.setX(value.x()) if self.parentItem().refLine and self.m_index == len(self.parentItem().points) - 2: points = self.parentItem().refLine.points point1 = points[self.parentItem().refIndex] point2 = points[self.parentItem().refIndex + 1] point1 = self.parentItem().mapFromItem(self.parentItem().refLine, point1) point2 = self.parentItem().mapFromItem(self.parentItem().refLine, point2) if p.x() < min(point1.x(), point2.x()): p.setX(min(point1.x(), point2.x())) elif p.x() > max(point1.x(), point2.x()): p.setX(max(point1.x(), point2.x())) elif self.direction == Qt.Vertical: p.setY(value.y()) if self.parentItem().refLine and self.m_index == len(self.parentItem().points) - 2: points = self.parentItem().refLine.points point1 = points[self.parentItem().refIndex] point2 = points[self.parentItem().refIndex + 1] point1 = self.parentItem().mapFromItem(self.parentItem().refLine, point1) point2 = self.parentItem().mapFromItem(self.parentItem().refLine, point2) if p.y() < min(point1.y(), point2.y()): p.setY(min(point1.y(), point2.y())) elif p.y() > max(point1.y(), point2.y()): p.setY(max(point1.y(), point2.y())) movement = p - self.pos() self.m_annotation_item.movePoints(self.m_index, movement) return p return super(Grabber, self).itemChange(change, value) def paint(self, painter, option, widget): """paints the path of grabber only if it is selected """ if self.isSelected() and not self.m_annotation_item.isSelected(): # show parent line of grabber self.m_annotation_item.setSelected(True) painter.setBrush(self.brush) painter.setPen(self.pen) painter.drawPath(self.path()) def shape(self): """Overrides shape method and set shape to segment on which grabber is located""" index = self.m_index # take start and end point of segment startPoint = QPointF(self.parentItem().points[index]) endPoint = QPointF(self.parentItem().points[index + 1]) # map in grabber's co-ordinate startPoint = self.mapFromParent(startPoint) endPoint = self.mapFromParent(endPoint) # create path as line path = QPainterPath(startPoint) path.lineTo(endPoint) # generate outlines for path stroke = QPainterPathStroker() stroke.setWidth(8) return stroke.createStroke(path) def boundingRect(self): return self.shape().boundingRect() def hoverEnterEvent(self, event): """ Changes cursor to horizontal movement or vertical movement depending on the direction of the grabber on mouse enter """ if self.direction == Qt.Horizontal: self.setCursor(QCursor(Qt.SplitHCursor)) else: self.setCursor(QCursor(Qt.SplitVCursor)) super(Grabber, self).hoverEnterEvent(event) def hoverLeaveEvent(self, event): """ reverts cursor to default on mouse leave """ self.setCursor(QCursor(Qt.ArrowCursor)) super(Grabber, self).hoverLeaveEvent(event) def show(self): # set pen to show self.pen = QPen(Qt.black, 2, Qt.SolidLine) self.brush = QBrush(Qt.cyan) def hide(self): # set pen to transparent self.pen = QPen(Qt.white, -1, Qt.SolidLine) self.brush = QBrush(Qt.transparent)
def drawValue(self, p: QPainter, baseRect: QRectF, value: float, delta: float): if value == self.m_min: return if self.m_barStyle == self.BarStyle.EXPAND: p.setBrush(self.palette().highlight()) p.setPen(QPen(self.palette().shadow().color(), self.m_dataPenWidth)) radius = (baseRect.height() / 2) / delta p.drawEllipse(baseRect.center(), radius, radius) return if self.m_barStyle == self.BarStyle.LINE: p.setPen( QPen(self.palette().highlight().color(), self.m_dataPenWidth)) p.setBrush(Qt.NoBrush) if value == self.m_max: p.drawEllipse( baseRect.adjusted(self.m_outlinePenWidth / 2, self.m_outlinePenWidth / 2, -self.m_outlinePenWidth / 2, -self.m_outlinePenWidth / 2)) else: arcLength = 360 / delta p.drawArc( baseRect.adjusted(self.m_outlinePenWidth / 2, self.m_outlinePenWidth / 2, -self.m_outlinePenWidth / 2, -self.m_outlinePenWidth / 2), int(self.m_nullPosition * 16), int(-arcLength * 16)) return dataPath = QPainterPath() dataPath.setFillRule(Qt.WindingFill) if value == self.m_max: dataPath.addEllipse(baseRect) else: arcLength = 360 / delta dataPath.moveTo(baseRect.center()) dataPath.arcTo(baseRect, self.m_nullPosition, -arcLength) dataPath.lineTo(baseRect.center()) p.setBrush(self.palette().highlight()) p.setPen(QPen(self.palette().shadow().color(), self.m_dataPenWidth)) p.drawPath(dataPath)
def paintEvent(self, e): if self.ready: qp = QPainter() qp.begin(self) path = QPainterPath() for x, y in zip(self.x, self.y): path.addRoundedRect(QRectF(x - 1, y - 1, 3, 3), 1, 1) qp.fillPath(path, Qt.darkGreen) qp.end() # print(self.x,self.y) if self.polylineOn: qp = QPainter() qp.begin(self) pen = QPen(Qt.darkRed, 2) qp.setPen(pen) # qp.drawLine(self.x[0],self.y[0],self.x[-1],self.y[-1]) for i in range(len(self.x)): qp.drawLine(self.x[i], self.y[i], self.x[i - 1], self.y[i - 1]) path = QPainterPath() for x, y in zip(self.x, self.y): path.addRoundedRect(QRectF(x - 2, y - 2, 5, 5), 2, 2) qp.fillPath(path, Qt.darkGreen) qp.end() if self.interpolationSplineOne: qp = QPainter() qp.begin(self) pen = QPen(Qt.black, 2) qp.setPen(pen) for i in range(self.x2.size - 1): qp.drawLine(self.x2[i], self.y2[i], self.x2[i + 1], self.y2[i + 1]) path = QPainterPath() for x, y in zip(self.x, self.y): path.addRoundedRect(QRectF(x - 2, y - 2, 5, 5), 2, 2) qp.fillPath(path, Qt.darkGreen) qp.end() if self.eulerianPlot: qp = QPainter() qp.begin(self) pen = QPen(Qt.darkCyan, 2) qp.setPen(pen) for i in range(self.x2.size): qp.drawLine(self.x2[i], self.y2[i], self.x2[i - 1], self.y2[i - 1]) path = QPainterPath() for x, y in zip(self.x, self.y): path.addRoundedRect(QRectF(x - 2, y - 2, 5, 5), 2, 2) qp.fillPath(path, Qt.darkGreen) qp.end() self.ready = False self.polylineOn = False self.interpolationSplineOne = False self.eulerianPlot = False
def shape(self): path = QPainterPath() path.addPolygon(self.polygonShape) return path
def paint(self, painter): if self.points: color = self.select_line_color if self.selected else self.line_color pen = QPen(color) # Try using integer sizes for smoother drawing(?) # pen.setWidth(max(1, int(round(2.0 / self.scale)))) pen.setWidth(max(1, int(round(5.0 / self.scale)))) painter.setPen(pen) line_path = QPainterPath() vrtx_path = QPainterPath() line_path.moveTo(self.points[0]) # Uncommenting the following line will draw 2 paths # for the 1st vertex, and make it non-filled, which # may be desirable. #self.draw_vertex(vrtx_path, 0) for i, p in enumerate(self.points): line_path.lineTo(p) self.draw_vertex(vrtx_path, i) if self.is_closed(): line_path.lineTo(self.points[0]) painter.drawPath(line_path) painter.drawPath(vrtx_path) painter.fillPath(vrtx_path, self.vertex_fill_color) # Draw text at the top-left if self.paint_label: min_x = sys.maxsize min_y = sys.maxsize for point in self.points: min_x = min(min_x, point.x()) min_y = min(min_y, point.y()) if min_x != sys.maxsize and min_y != sys.maxsize: pen = QPen() pen.setWidth(3) pen.setColor(QColor(0, 0, 0)) painter.setRenderHint(QPainter.Antialiasing, True) painter.setPen(pen) linear_grad = QLinearGradient() linear_grad.setColorAt(0, QColor(255, 255, 255)) font = QFont() font.setPointSize(25) font.setBold(True) font.setFamily("Microsoft YaHei") min_y += MIN_Y_LABEL if len(self.label) > 0: text_path = QPainterPath() if self._current_label_text: text_path.addText(min_x, min_y, font, self._current_label_text) else: text_path.addText(min_x, min_y, font, self.label[0]) # 应该取最后一个比较合理 painter.setBrush(linear_grad) painter.drawPath(text_path) min_y += 25 painter.setBrush(Qt.NoBrush) if self.fill: color = self.select_fill_color if self.selected else self.fill_color painter.fillPath(line_path, color)
def make_path(self): path = QPainterPath(self.points[0]) for p in self.points[1:]: path.lineTo(p) return path
def drawObject(self, painter: 'QPainter', rect: QtCore.QRectF, doc: 'QTextDocument', pos_in_document: int, format_: 'QTextFormat') -> None: painter.setRenderHint(QPainter.Antialiasing, True) c = QColor(255, 80, 0, 160) painter.setBrush(QBrush(c, Qt.SolidPattern)) painter.setPen(QPen(QtCore.Qt.white, 2, QtCore.Qt.SolidLine)) tag_kind: TagKind = format_.property(TagTextObject.kind_propid) top = rect.top() left = rect.left() width = rect.width() height = rect.height() square_size = rect.height() / 2 if tag_kind == TagKind.START: path = QPainterPath() path.setFillRule(Qt.WindingFill) path.addRoundedRect(rect, 10, 10) # QRectF(aleft: float, atop: float, awidth: float, aheight: float) bottom_left_rect = QRectF(left, top + height - square_size, square_size, square_size) path.addRoundedRect(bottom_left_rect, 2, 2) # Bottom left top_left_rect = QRectF(left, top, square_size, square_size) path.addRoundedRect(top_left_rect, 2, 2) # Top left painter.drawPath(path.simplified()) elif tag_kind == TagKind.END: path = QPainterPath() path.setFillRule(Qt.WindingFill) path.addRoundedRect(rect, 10, 10) top_right_rect = QRectF((left + width) - square_size, top, square_size, square_size) path.addRoundedRect(top_right_rect, 2, 2) # Top right bottom_right_rect = QRectF((left + width) - square_size, top + height - square_size, square_size, square_size) path.addRoundedRect(bottom_right_rect, 2, 2) # Bottom right painter.drawPath(path.simplified()) else: painter.drawRoundedRect(rect, 4, 4) tag_name = format_.property(TagTextObject.name_propid) painter.drawText(rect, QtCore.Qt.AlignHCenter | QtCore.Qt.AlignCenter, tag_name)
def bulletShape(self): shape = QPainterPath() shape.addEllipse(self.position.x() - (0.5 * Bullet_Size), self.position.y() - (0.5 * Bullet_Size), Bullet_Size, Bullet_Size) return shape
def paintEvent(self, event): self.gt = GetGCPGeoTransform() # TODO : Here? painter = QPainter(self) if (self.surface.isActive()): videoRect = self.surface.videoRect() if not videoRect.contains(event.rect()): region = event.region() region.subtracted(QRegion(videoRect)) brush = self.palette().window() for rect in region.rects(): painter.fillRect(rect, brush) try: self.surface.paint(painter) except: None else: painter.fillRect(event.rect(), self.palette().window()) try: SetImageSize(self.surface.currentFrame.width(), self.surface.currentFrame.height()) except: None # Magnifier Glass if self.zoomed and magnifier: dim = min(self.width(), self.height()) magnifierSize = min(MAX_MAGNIFIER, dim * 2 / 3) radius = magnifierSize / 2 ring = radius - 15 box = QSize(magnifierSize, magnifierSize) # reupdate our mask if self.maskPixmap.size() != box: self.maskPixmap = QPixmap(box) self.maskPixmap.fill(Qt.transparent) g = QRadialGradient() g.setCenter(radius, radius) g.setFocalPoint(radius, radius) g.setRadius(radius) g.setColorAt(1.0, QColor(64, 64, 64, 0)) g.setColorAt(0.5, QColor(0, 0, 0, 255)) mask = QPainter(self.maskPixmap) mask.setRenderHint(QPainter.Antialiasing) mask.setCompositionMode(QPainter.CompositionMode_Source) mask.setBrush(g) mask.setPen(Qt.NoPen) mask.drawRect(self.maskPixmap.rect()) mask.setBrush(QColor(Qt.transparent)) mask.drawEllipse(g.center(), ring, ring) mask.end() center = self.dragPos - QPoint(0, radius) center += QPoint(0, radius / 2) corner = center - QPoint(radius, radius) xy = center * 2 - QPoint(radius, radius) # only set the dimension to the magnified portion if self.zoomPixmap.size() != box: self.zoomPixmap = QPixmap(box) self.zoomPixmap.fill(Qt.lightGray) if True: painter = QPainter(self.zoomPixmap) painter.translate(-xy) self.largePixmap = QPixmap.fromImage(self.surface.image) painter.drawPixmap(self.offset * 2, self.largePixmap) painter.end() clipPath = QPainterPath() clipPath.addEllipse(QPointF(center), ring, ring) painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.setClipPath(clipPath) painter.drawPixmap(corner, self.zoomPixmap) # painter.setClipping(False) painter.drawPixmap(corner, self.maskPixmap) painter.setPen(Qt.gray) painter.drawPath(clipPath)
def __init__(self, diagramType, contextMenu, parent=None): super(DiagramItem, self).__init__(parent) self.arrows = [] self.diagramType = diagramType self.contextMenu = contextMenu path = QPainterPath() if self.diagramType == self.StartEnd: path.moveTo(200, 50) path.arcTo(150, 0, 50, 50, 0, 90) path.arcTo(50, 0, 50, 50, 90, 90) path.arcTo(50, 50, 50, 50, 180, 90) path.arcTo(150, 50, 50, 50, 270, 90) path.lineTo(200, 25) self.myPolygon = path.toFillPolygon() elif self.diagramType == self.Conditional: self.myPolygon = QPolygonF([ QPointF(-100, 0), QPointF(0, 100), QPointF(100, 0), QPointF(0, -100), QPointF(-100, 0) ]) elif self.diagramType == self.Step: self.myPolygon = QPolygonF([ QPointF(-100, -100), QPointF(100, -100), QPointF(100, 100), QPointF(-100, 100), QPointF(-100, -100) ]) else: self.myPolygon = QPolygonF([ QPointF(-120, -80), QPointF(-70, 80), QPointF(120, 80), QPointF(70, -80), QPointF(-120, -80) ]) self.setPolygon(self.myPolygon) self.setFlag(QGraphicsItem.ItemIsMovable, True) self.setFlag(QGraphicsItem.ItemIsSelectable, True)
def drawEdge(self, x1, y1, x2, y2, index, curve, tear=False): ''' Draw an edge from x1, y1 to x2, y2. Edges connect two nodes --Args-- index: the edge index curve: distance from center of straight edge to a point on curved edge (can be positive or negitive. Used to keep edges from overlapping. tear: if true draw in tear edge style ''' # determine if edge conntects a node to itself. if abs(x1 - x2) < 0.01 and abs(y1 - y2) < 0.01: path = QPainterPath() curve = curve * 2 path.addEllipse(x1, y1 - curve / 2.0, curve, curve) if tear: gi = self.addPath(path, self.edgePen) else: gi = self.addPath(path, self.tearEdgePen) else: # mid point of the edge if it is a straight line xmid = (x1 + x2) / 2.0 ymid = (y1 + y2) / 2.0 # get the angle of the edge and the angle perpendicular ang = math.atan2((y2 - y1), (x2 - x1)) ang_perp = math.atan2((x1 - x2), (y2 - y1)) # calculate the mid point of the curved edge xcurve = xmid + curve * math.cos(ang_perp) ycurve = ymid + curve * math.sin(ang_perp) # calculate control point for drawing quaratic curve xcontrol = 2 * xcurve - xmid ycontrol = 2 * ycurve - ymid #draw Edge path = QPainterPath() path.moveTo(x1, y1) path.quadTo(xcontrol, ycontrol, x2, y2) p2 = QPainterPathStroker() path = p2.createStroke(path) # if edge is selected draw it highlighted if index in self.selectedEdges: self.addPath(path, self.eSelectionPen) # if edge is a tear draw it tear style else draw it normal if tear: gi = self.addPath(path, self.tearEdgePen) else: gi = self.addPath(path, self.edgePen) # Add data to edge so if seleted we can determine that it # is an edge and which edge it is. gi.setData(1, index) gi.setData(2, "edge") # Draw the arrow path = QPainterPath() xs = xcurve + self.edgeArrowSize * math.cos(ang) ys = ycurve + self.edgeArrowSize * math.sin(ang) path.moveTo(xs, ys) path.lineTo( xs - self.edgeArrowSize*math.cos(ang) +\ self.edgeArrowSize/2.0*math.cos(ang_perp), ys - self.edgeArrowSize*math.sin(ang) +\ self.edgeArrowSize/2.0*math.sin(ang_perp)) path.lineTo( xs - self.edgeArrowSize*math.cos(ang) -\ self.edgeArrowSize/2.0*math.cos(ang_perp), ys - self.edgeArrowSize*math.sin(ang) -\ self.edgeArrowSize/2.0*math.sin(ang_perp)) path.lineTo(xs, ys) gi = self.addPath(path, self.edgePen, self.edgeArrowBrush) # Add data so selecting the arrow in like selecting the edge gi.setData(1, index) gi.setData(2, "edge")
class Canvas(QWidget): def __init__(self, parent=None): super(Canvas, self).__init__(parent) self.is_enable_knee_control = False # 画像専用のレイヤであるかを制御する # 1度Trueになったら2度とFalseにならないことを意図する self.is_picture_canvas = False self.picture_file_name = "" self.image = QImage() # マウストラック有効化 self.setMouseTracking(True) # マウス移動で出る予測線とクリックして出る本線を描画するときに区別する self.is_line_prediction = False # イベント同士の競合を防ぐ self.event_Locker = False self.rounded_polygon = RoundedPolygon(10000) self.existing_paths = [] # 確定したパスを保存 self.recorded_points = [] # 確定した点を保存(実験の記録用) self.clicked_points = [] # 今描いている線の制御点を記録 self.cursor_position = QPointF() self.cursor_position_mousePressed = QPointF() self.knee_position = QPointF() self.knee_position_mousePressed = QPointF() self.current_drawing_mode = OperationMode.DRAWING_POINTS self.current_knee_operation_mode = OperationMode.NONE self.__line_color = [] self.current_line_color = QColor() self.nearest_path = QPainterPath() self.nearest_distance = 50.0 self.nearest_index = 0 self.is_dragging = False self.pen_width = 2 self.show() def set_experiment_controller(self, excontroller): self.experiment_controller = excontroller def mousePressEvent(self, event: QMouseEvent): if self.current_drawing_mode == OperationMode.DRAWING_POINTS: # 制御点の追加 if event.button() == Qt.LeftButton: self.clicked_points.append(event.pos()) # print(self.clickedPoints) # 直前の制御点の消去 if event.button() == Qt.RightButton: if len(self.clicked_points) > 0: self.clicked_points.pop() self.update() elif self.current_drawing_mode == OperationMode.MOVING_POINTS: if event.button() == Qt.LeftButton: self.is_dragging = True if self.is_enable_knee_control: self.recode_knee_and_cursor_position() self.cursor_position = event.pos() self.update() def mouseMoveEvent(self, event: QMouseEvent): self.experiment_controller.current_mouse_position = event.pos() self.experiment_controller.record_frame( self.current_drawing_mode, self.current_knee_operation_mode) if self.current_drawing_mode == OperationMode.DRAWING_POINTS: self.clicked_points.append(event.pos()) self.is_line_prediction = True self.update() elif self.current_drawing_mode == OperationMode.MOVING_POINTS: print(self.nearest_distance) self.cursor_position = event.pos() if self.is_dragging: self.move_point() self.update() def mouseReleaseEvent(self, event: QMouseEvent): self.is_dragging = False def paintEvent(self, event: QPaintEvent): # if not self.event_Locker: painter = QPainter(self) if self.is_picture_canvas: painter.drawImage(QRect(0, 0, 600, 600), self.image) else: # すでに確定されているパスの描画 if len(self.existing_paths) > 0: for i in range(len(self.existing_paths)): print("linecolor {}: {}".format( i, self.__line_color[i].hue())) painter.setPen(QPen(self.__line_color[i], self.pen_width)) painter.drawPath(self.existing_paths[i]) if self.current_drawing_mode == OperationMode.DRAWING_POINTS: # 現在描いているパスの描画 if len(self.clicked_points) > 3: painter.setPen( QPen(self.current_line_color, self.pen_width)) # print(self.clickedPoints) # クリックした点まで線を伸ばすため、終点を一時的にリストに入れている self.clicked_points.append( self.clicked_points[len(self.clicked_points) - 1]) painter_path = self.rounded_polygon.get_path( self.clicked_points) # 設置した点の描画 painter.setPen(Qt.black) for i in range(len(self.clicked_points)): painter.drawEllipse(self.clicked_points[i], 2, 2) painter.setPen( QPen(self.current_line_color, self.pen_width)) # 現在のマウス位置での予告線 if self.is_line_prediction: self.clicked_points.pop() self.is_line_prediction = False painter.drawPath(painter_path) self.clicked_points.pop() # 線が描けない時 else: # 現在のマウス位置での予告線 if self.is_line_prediction: painter.setPen(Qt.red) for i in range(len(self.clicked_points)): painter.drawEllipse(self.clicked_points[i], 2, 2) if not len(self.clicked_points) == 0: self.clicked_points.pop() self.is_line_prediction = False # 予告線でもない場合は単に点を書く else: for i in range(len(self.clicked_points)): painter.drawEllipse(self.clicked_points[i], 2, 2) # 制御点を移動するとき elif self.current_drawing_mode == OperationMode.MOVING_POINTS: # すでに確定されているパスの制御点の描画 self.nearest_distance = 50.0 painter.setPen(Qt.black) for path in self.existing_paths: for i in range(path.elementCount()): control_point = QPointF( path.elementAt(i).x, path.elementAt(i).y) painter.drawEllipse(control_point, 3, 3) # 現在のカーソル位置から最も近い点と、その点が属するpathを記録、更新 # if not self.is_dragging & self.is_enable_knee_control: distance = math.sqrt( (control_point.x() - self.cursor_position.x())**2 + (control_point.y() - self.cursor_position.y())**2) if distance < self.nearest_distance: self.nearest_distance = distance self.nearest_path = path self.nearest_index = i # 一定の距離未満かつ最も近い点を赤く描画 if self.nearest_distance < 20: painter.setPen(QPen(Qt.red, self.pen_width)) nearest_control_point = QPointF( self.nearest_path.elementAt(self.nearest_index).x, self.nearest_path.elementAt(self.nearest_index).y) painter.drawEllipse(nearest_control_point, 3, 3) def move_point(self): if self.is_enable_knee_control: if self.nearest_distance < 20 or self.is_dragging: self.nearest_path.setElementPositionAt( self.nearest_index, self.cursor_position.x(), self.cursor_position.y()) amount_of_change = QPointF( self.cursor_position.x() + (self.knee_position.x() - self.knee_position_mousePressed.x()), self.cursor_position.y() - (self.knee_position.y() - self.knee_position_mousePressed.y())) self.nearest_path.setElementPositionAt(self.nearest_index, amount_of_change.x(), amount_of_change.y()) else: if self.nearest_distance < 20: self.nearest_path.setElementPositionAt( self.nearest_index, self.cursor_position.x(), self.cursor_position.y()) def set_knee_position(self, x, y): self.knee_position.setX(x) self.knee_position.setY(y) if self.is_dragging: if self.current_drawing_mode == OperationMode.MOVING_POINTS: self.move_point() self.update() def set_line_color(self, color): self.current_line_color = color def recode_knee_and_cursor_position(self): self.knee_position_mousePressed.setX(self.knee_position.x()) self.knee_position_mousePressed.setY(self.knee_position.y()) self.cursor_position_mousePressed = self.cursor_position def fix_path(self): # パスを確定 if self.is_line_prediction and not len(self.clicked_points) == 0: self.clicked_points.pop() # クリックした点まで線を伸ばすため、終点をリストに入れている if len(self.clicked_points) > 0: self.clicked_points.append( self.clicked_points[len(self.clicked_points) - 1]) painter_path = self.rounded_polygon.get_path(self.clicked_points) # 線と色を記録 self.existing_paths.append(painter_path) self.__line_color.append(self.current_line_color) for i in range(len(self.__line_color)): print("{}, {}".format(i, self.__line_color[i].value())) self.clicked_points.pop() self.recorded_points.append(self.clicked_points) # 点をリセット self.clicked_points = [] self.update() def delete_last_path(self): if len(self.existing_paths) > 0: self.existing_paths.pop() self.__line_color.pop() self.update() def switch_visible(self, is_visible: bool): palette = self.palette() if is_visible: palette.setColor(QPalette.Background, QColor(255, 255, 255, 120)) else: palette.setColor(QPalette.Background, QColor(255, 255, 255, 255)) self.setPalette(palette) def operation_mode_changed(self, to_drawing: OperationMode, to_knee: OperationMode): self.current_drawing_mode = to_drawing self.current_knee_operation_mode = to_knee self.fix_path() def set_picture_file_name(self, picture_file_name: str): self.is_picture_canvas = True self.picture_file_name = picture_file_name self.update() def set_enable_knee_control(self, is_enable_knee_control): self.is_enable_knee_control = is_enable_knee_control def load_picture(self, image: QImage): self.image = image self.is_picture_canvas = True self.update()
def createPath(self): """ creates initial path and stores it's points :return: """ offset = 30 x0, y0 = self.startPoint.x(), self.startPoint.y() x1, y1 = self.endPoint.x(), self.endPoint.y() # create path for line in process self.points = [self.startPoint, QPointF((x0 + x1) / 2, y0), QPointF((x0 + x1) / 2, y1), self.endPoint] # final path of line if self.refLine: # line has end point on other line from .shapes import LineGripItem direction = "left" points = self.refLine.points point1 = points[self.refIndex] point2 = points[self.refIndex + 1] if point1.x() == point2.x(): if point1.x() < self.startPoint.x(): direction = "right" else: direction = "left" elif point1.y() == point2.y(): if point1.y() > self.startPoint.y(): direction = "top" else: direction = "bottom" self.endGripItem = LineGripItem(-1, [0, 0, direction], self) self.endGripItem.setPos(self.endPoint) if self.startGripItem and self.endGripItem: # determine ns (point next to start) item = self.startGripItem if item.m_location == "top": ns = QPointF(self.startPoint.x(), self.startPoint.y() - offset) elif item.m_location == "left": ns = QPointF(self.startPoint.x() - offset, self.startPoint.y()) elif item.m_location == "bottom": ns = QPointF(self.startPoint.x(), self.startPoint.y() + offset) else: ns = QPointF(self.startPoint.x() + offset, self.startPoint.y()) # determine pe (point previous to end) item = self.endGripItem if item.m_location == "top": pe = QPointF(self.endPoint.x(), self.endPoint.y() - offset) elif item.m_location == "left": pe = QPointF(self.endPoint.x() - offset, self.endPoint.y()) elif item.m_location == "bottom": pe = QPointF(self.endPoint.x(), self.endPoint.y() + offset) else: pe = QPointF(self.endPoint.x() + offset, self.endPoint.y()) start = self.startPoint end = self.endPoint sitem = self.startGripItem.mapRectToScene(self.startGripItem.parentItem().boundingRect()) eitem = self.endGripItem.mapRectToScene(self.endGripItem.parentItem().boundingRect()) if self.refLine: eitem = self.endGripItem.mapRectToScene(QRectF(0, 0, 0, 0)) if self.startGripItem.m_location in ["right"]: if self.endGripItem.m_location in ["top"]: if start.x() + offset < end.x(): if start.y() + offset < end.y(): self.points = [start, QPointF(end.x(), start.y()), end] else: if start.x() + offset < eitem.left() - offset: self.points = [start, ns, QPointF(ns.x(), pe.y()), pe, end] else: x = max(eitem.right() + offset, ns.x()) self.points = [start, QPointF(x, start.y()), QPointF(x, pe.y()), pe, end] elif sitem.left() > end.x(): if sitem.bottom() + offset < end.y(): self.points = [start, ns, QPointF(ns.x(), pe.y()), pe, end] elif sitem.top() - offset < end.y(): self.points = [start, ns, QPointF(ns.x(), sitem.top() - offset), QPointF(pe.x(), sitem.top() - offset), end] else: self.points = [start, ns, QPointF(ns.x(), pe.y()), pe, end] else: self.points = [start, ns, QPointF(ns.x(), pe.y()), pe, end] if start.y() > end.y(): x = max(eitem.right() + offset, ns.x()) self.points = [start, QPointF(x, start.y()), QPointF(x, pe.y()), pe, end] elif self.endGripItem.m_location in ["bottom"]: if start.x() + offset < eitem.left(): if start.y() - offset < end.y(): self.points = [start, ns, QPointF(ns.x(), pe.y()), pe, end] else: self.points = [start, QPointF(end.x(), start.y()), end] elif sitem.left() > end.x(): if sitem.bottom() + offset < end.y(): self.points = [start, ns, QPointF(ns.x(), pe.y()), pe, end] elif sitem.top() - offset < end.y(): y = max(pe.y(), sitem.bottom() + offset) self.points = [start, ns, QPointF(ns.x(), y), QPointF(pe.x(), y), end] else: self.points = [start, ns, QPointF(ns.x(), pe.y()), pe, end] else: self.points = [start, ns, QPointF(ns.x(), pe.y()), pe, end] if start.y() < end.y(): x = max(eitem.right() + offset, ns.x()) self.points = [start, QPointF(x, start.y()), QPointF(x, pe.y()), pe, end] elif self.endGripItem.m_location in ["right"]: x = max(start.x() + offset, pe.x()) self.points = [start, QPointF(x, start.y()), QPointF(x, end.y()), end] if start.x() + offset < eitem.top(): if start.y() + offset > eitem.top() and end.y() >= start.y(): self.points = [start, ns, QPointF(ns.x(), eitem.top()), QPointF(pe.x(), eitem.top()), pe, end] elif start.y() - offset < eitem.bottom() and end.y() <= start.y(): self.points = [start, ns, QPointF(ns.x(), eitem.bottom()), QPointF(pe.x(), eitem.bottom()), pe, end] elif sitem.top() - offset < end.y() < sitem.bottom() + offset: if end.y() < start.y(): self.points = [start, ns, QPointF(ns.x(), sitem.top()), QPointF(pe.x(), sitem.top()), pe, end] else: self.points = [start, ns, QPointF(ns.x(), sitem.bottom()), QPointF(pe.x(), sitem.bottom()), pe, end] elif self.endGripItem.m_location in ["left"]: self.points = [start, QPointF((start.x() + end.x()) / 2, start.y()), QPointF((start.x() + end.x()) / 2, end.y()), end] if end.x() < start.x() + offset: if eitem.bottom() <= sitem.top() - offset: self.points = [start, ns, QPointF(ns.x(), sitem.top()), QPointF(pe.x(), sitem.top()), pe, end] elif eitem.top() >= sitem.bottom() + offset: self.points = [start, ns, QPointF(ns.x(), sitem.bottom()), QPointF(pe.x(), sitem.bottom()), pe, end] elif end.y() <= start.y(): y = min(eitem.top(), sitem.top()) self.points = [start, ns, QPointF(ns.x(), y), QPointF(pe.x(), y), pe, end] else: y = max(eitem.bottom(), sitem.bottom()) self.points = [start, ns, QPointF(ns.x(), y), QPointF(pe.x(), y), pe, end] elif self.startGripItem.m_location in ["left"]: if self.endGripItem.m_location in ["top"]: if start.x() + offset < eitem.left(): if end.y() > sitem.bottom() + offset: self.points = [start, ns, QPointF(ns.x(), sitem.bottom()), QPointF(pe.x(), sitem.bottom()), end] else: y = min(sitem.top(), pe.y()) self.points = [start, ns, QPointF(ns.x(), y), QPointF(pe.x(), y), end] elif eitem.right() >= start.x() - offset: x = min(ns.x(), eitem.left()) self.points = [start, QPointF(x, ns.y()), QPointF(x, pe.y()), pe, end] else: if end.y() >= start.y() + offset: self.points = [start, QPointF(end.x(), start.y()), end] else: x = (start.x() + end.x()) / 2 self.points = [start, QPointF(x, start.y()), QPointF(x, pe.y()), pe, end] elif self.endGripItem.m_location in ["bottom"]: if start.x() + offset < eitem.left(): if end.y() < sitem.top() - offset: self.points = [start, ns, QPointF(ns.x(), sitem.top()), QPointF(pe.x(), sitem.top()), end] else: y = max(sitem.bottom(), pe.y()) self.points = [start, ns, QPointF(ns.x(), y), QPointF(pe.x(), y), end] elif eitem.right() >= start.x() - offset: x = min(ns.x(), eitem.left()) self.points = [start, QPointF(x, ns.y()), QPointF(x, pe.y()), pe, end] else: if end.y() <= start.y() - offset: self.points = [start, QPointF(end.x(), start.y()), end] else: x = (start.x() + end.x()) / 2 self.points = [start, QPointF(x, start.y()), QPointF(x, pe.y()), pe, end] elif self.endGripItem.m_location in ["right"]: self.points = [start, QPointF((start.x() + end.x()) / 2, start.y()), QPointF((start.x() + end.x()) / 2, end.y()), end] if end.x() > start.x() + offset: if eitem.bottom() <= sitem.top() - offset: self.points = [start, ns, QPointF(ns.x(), sitem.top()), QPointF(pe.x(), sitem.top()), pe, end] elif eitem.top() >= sitem.bottom() + offset: self.points = [start, ns, QPointF(ns.x(), sitem.bottom()), QPointF(pe.x(), sitem.bottom()), pe, end] elif end.y() <= start.y(): y = min(eitem.top(), sitem.top()) self.points = [start, ns, QPointF(ns.x(), y), QPointF(pe.x(), y), pe, end] else: y = max(eitem.bottom(), sitem.bottom()) self.points = [start, ns, QPointF(ns.x(), y), QPointF(pe.x(), y), pe, end] elif self.endGripItem.m_location in ["left"]: self.points = [start, QPointF(pe.x(), start.y()), pe, end] if start.x() + offset < end.x(): self.points = [start, ns, QPointF(ns.x(), end.y()), end] if sitem.bottom() + offset > end.y() > sitem.top() - offset: self.points = [start, ns, QPointF(ns.x(), sitem.top()), QPointF(pe.x(), sitem.top()), pe, end] elif eitem.top() - offset < start.y() < eitem.bottom() + offset: if end.y() > start.y(): self.points = [start, ns, QPointF(ns.x(), eitem.top()), QPointF(pe.x(), eitem.top()), pe, end] else: self.points = [start, ns, QPointF(ns.x(), eitem.bottom()), QPointF(pe.x(), eitem.bottom()), pe, end] elif self.startGripItem.m_location in ["top"]: if self.endGripItem.m_location in ["top"]: self.points = [self.startPoint, QPointF(start.x(), pe.y()), pe, self.endPoint] if start.y() < end.y(): self.points = [self.startPoint, ns, QPointF(pe.x(), ns.y()), self.endPoint] if sitem.right() > end.x() > sitem.left() or eitem.right() > start.x() > eitem.left(): x = max(sitem.right(), eitem.right()) x += offset if start.x() > end.x(): x = min(sitem.left(), eitem.left()) x -= offset self.points = [start, ns, QPointF(x, ns.y()), QPointF(x, pe.y()), pe, end] elif self.endGripItem.m_location in ["bottom"]: self.points = [self.startPoint, ns, QPointF((x0 + x1) / 2, ns.y()), QPointF((x0 + x1) / 2, pe.y()), pe, self.endPoint] if start.y() - offset > end.y(): self.points = [start, QPointF(start.x(), (y0 + y1) / 2), QPointF(end.x(), (y0 + y1) / 2), self.endPoint] elif sitem.right() > end.x() > sitem.left() or eitem.right() > start.x() > eitem.left(): x = max(sitem.right(), eitem.right()) x += offset if start.x() > end.x(): x = min(sitem.left(), eitem.left()) x -= offset self.points = [start, ns, QPointF(x, ns.y()), QPointF(x, pe.y()), pe, end] elif self.endGripItem.m_location in ["right"]: y = min(ns.y(), eitem.bottom() + offset) self.points = [start, QPointF(ns.x(), y), QPointF(pe.x(), y), pe, end] if sitem.left() - offset < end.x() < sitem.right() + offset and end.y() > start.y() + offset: self.points = [start, ns, QPointF(sitem.right() + offset, ns.y()), QPointF(sitem.right() + offset, pe.y()), end] elif eitem.top() < start.y() - offset < eitem.bottom(): self.points = [start, ns, QPointF(start.x(), eitem.top()), QPointF(pe.x(), eitem.top()), pe, end] elif self.endGripItem.m_location in ["left"]: y = min(ns.y(), eitem.bottom() + offset) self.points = [start, QPointF(ns.x(), y), QPointF(pe.x(), y), pe, end] if sitem.left() - offset < end.x() < sitem.right() + offset and end.y() > start.y() + offset: self.points = [start, ns, QPointF(sitem.left() - offset, ns.y()), QPointF(sitem.left() - offset, pe.y()), end] elif eitem.top() < start.y() - offset < eitem.bottom(): self.points = [start, QPointF(start.x(), eitem.top()), QPointF(pe.x(), eitem.top()), pe, end] elif self.startGripItem.m_location in ["bottom"]: if self.endGripItem.m_location in ["top"]: self.points = [self.startPoint, ns, QPointF((x0 + x1) / 2, ns.y()), QPointF((x0 + x1) / 2, pe.y()), pe, self.endPoint] if start.y() < end.y(): self.points = [self.startPoint, ns, QPointF(pe.x(), ns.y()), self.endPoint] if sitem.right() > end.x() > sitem.left() or eitem.right() > start.x() > eitem.left(): x = max(sitem.right(), eitem.right()) x += offset self.points = [start, ns, QPointF(x, ns.y()), QPointF(x, pe.y()), pe, end] elif self.endGripItem.m_location in ["bottom"]: self.points = [self.startPoint, ns, QPointF((x0 + x1) / 2, ns.y()), QPointF((x0 + x1) / 2, pe.y()), pe, self.endPoint] if sitem.right() > end.x() > sitem.left() or eitem.right() > start.x() > eitem.left(): x = max(sitem.right(), eitem.right()) x += offset self.points = [start, ns, QPointF(x, ns.y()), QPointF(x, pe.y()), pe, end] elif self.endGripItem.m_location in ["right"]: y = max(ns.y(), eitem.bottom() + offset) self.points = [start, QPointF(ns.x(), y), QPointF(pe.x(), y), pe, end] if sitem.left() - offset < end.x() < sitem.right() + offset: self.points = [start, ns, QPointF(sitem.right() + offset, ns.y()), QPointF(sitem.right() + offset, pe.y()), end] elif self.endGripItem.m_location in ["left"]: y = max(ns.y(), eitem.bottom() + offset) self.points = [start, QPointF(ns.x(), y), QPointF(pe.x(), y), pe, end] if sitem.left() - offset < end.x() < sitem.right() + offset: self.points = [start, ns, QPointF(sitem.left() - offset, ns.y()), QPointF(sitem.left() - offset, pe.y()), end] # path of line path = QPainterPath(self.startPoint) for i in range(1, len(self.points)): path.lineTo(self.points[i]) self.setPath(path) if self.refLine: # remove added grip self.scene().removeItem(self.endGripItem) self.endGripItem = None self.addGrabber() if self.endGripItem: self.addGrabber()
class StMoveGUI(QGraphicsLineItem, StMove): def __init__(self, shape): QGraphicsLineItem.__init__(self) StMove.__init__(self, shape) self.allwaysshow = False self.path = QPainterPath() self.setFlag(QGraphicsItem.ItemIsSelectable, False) self.pen = QPen(QColor(50, 100, 255), 1, QtCore.Qt.SolidLine, QtCore.Qt.RoundCap, QtCore.Qt.RoundJoin) self.pen.setCosmetic(True) self.make_papath() def contains_point(self, point): """ StMove cannot be selected. Return maximal distance """ return float(0x7fffffff) def make_papath(self): """ To be called if a Shape shall be printed to the canvas @param canvas: The canvas to be printed in @param pospro: The color of the shape """ self.path = QPainterPath() if len(self.geos): start = self.geos.abs_el(0).get_start_end_points(True) self.path.moveTo(start.x, -start.y) drawHorLine = lambda caller, start, end: self.path.lineTo( end.x, -end.y) drawVerLine = lambda caller, start: None # Not used in 2D mode self.make_path(drawHorLine, drawVerLine) def setSelected(self, flag=True): """ Override inherited function to turn off selection of Arrows. @param flag: The flag to enable or disable Selection """ if self.allwaysshow: pass elif flag is True: self.show() else: self.hide() def setallwaysshow(self, flag=False): """ If the directions shall be allwaysshown the parameter will be set and all paths will be shown. @param flag: The flag to enable or disable Selection """ self.allwaysshow = flag if flag is True: self.show() elif flag is True and self.isSelected(): self.show() else: self.hide() def paint(self, painter, option, widget=None): """ Method will be triggered with each paint event. Possible to give options @param painter: Reference to std. painter @param option: Possible options here @param widget: The widget which is painted on. """ painter.setPen(self.pen) painter.drawPath(self.path) def boundingRect(self): """ Required method for painting. Inherited by Painterpath @return: Gives the Bounding Box """ return self.path.boundingRect()
def paint(self, painter): painter.setRenderHint(QPainter.Antialiasing) pixelRatio = self.devicePixelRatioF() rect = QRectF(0, 0, self.width() * pixelRatio, self.height() * pixelRatio) sz = QSizeF(self.width() * pixelRatio, self.height() * pixelRatio).toSize() self.resizePixmap(sz) yOffset = rect.toRect().topLeft().y() + (100 - self.value() - 10) * sz.height() / 100 # draw water waterImage = QImage(sz, QImage.Format_ARGB32_Premultiplied) waterPainter = QPainter() waterPainter.begin(waterImage) waterPainter.setRenderHint(QPainter.Antialiasing) waterPainter.setCompositionMode(QPainter.CompositionMode_Source) pointStart = QPointF(sz.width() / 2, 0) pointEnd = QPointF(sz.width() / 2, sz.height()) linear = QLinearGradient(pointStart, pointEnd) startColor = QColor('#1F08FF') startColor.setAlphaF(1) endColor = QColor('#50FFF7') endColor.setAlphaF(0.28) linear.setColorAt(0, startColor) linear.setColorAt(1, endColor) linear.setSpread(QGradient.PadSpread) waterPainter.setPen(Qt.NoPen) waterPainter.setBrush(linear) waterPainter.drawEllipse(waterImage.rect().center(), sz.width() / 2 + 1, sz.height() / 2 + 1) waterPainter.setCompositionMode(QPainter.CompositionMode_SourceOver) waterPainter.drawImage(int(self.backXOffset), yOffset, self.waterBackImage) waterPainter.drawImage( int(self.backXOffset) - self.waterBackImage.width(), yOffset, self.waterBackImage) waterPainter.drawImage(int(self.frontXOffset), yOffset, self.waterFrontImage) waterPainter.drawImage( int(self.frontXOffset) - self.waterFrontImage.width(), yOffset, self.waterFrontImage) # draw pop if self.value() > 30: for pop in self.pops: popPath = QPainterPath() popPath.addEllipse(pop.xOffset * sz.width() / 100, (100 - pop.yOffset) * sz.height() / 100, pop.size * sz.width() / 100, pop.size * sz.height() / 100) waterPainter.fillPath(popPath, QColor(255, 255, 255, 255 * 0.3)) if self.isTextVisible(): font = waterPainter.font() rectValue = QRect() progressText = self.text().strip('%') if progressText == '100': font.setPixelSize(sz.height() * 35 / 100) waterPainter.setFont(font) rectValue.setWidth(sz.width() * 60 / 100) rectValue.setHeight(sz.height() * 35 / 100) rectValue.moveCenter(rect.center().toPoint()) waterPainter.setPen(Qt.white) waterPainter.drawText(rectValue, Qt.AlignCenter, progressText) else: font.setPixelSize(sz.height() * 40 / 100) waterPainter.setFont(font) rectValue.setWidth(sz.width() * 45 / 100) rectValue.setHeight(sz.height() * 40 / 100) rectValue.moveCenter(rect.center().toPoint()) rectValue.moveLeft(rect.left() + rect.width() * 0.45 * 0.5) waterPainter.setPen(Qt.white) waterPainter.drawText(rectValue, Qt.AlignCenter, progressText) font.setPixelSize(font.pixelSize() / 2) waterPainter.setFont(font) rectPerent = QRect( QPoint(rectValue.right(), rectValue.bottom() - rect.height() * 20 / 100), QPoint(rectValue.right() + rect.width() * 20 / 100, rectValue.bottom())) waterPainter.drawText(rectPerent, Qt.AlignCenter, '%') waterPainter.end() maskPixmap = QPixmap(sz) maskPixmap.fill(Qt.transparent) path = QPainterPath() path.addEllipse(QRectF(0, 0, sz.width(), sz.height())) maskPainter = QPainter() maskPainter.begin(maskPixmap) maskPainter.setRenderHint(QPainter.Antialiasing) maskPainter.setPen(QPen(Qt.white, 1)) maskPainter.fillPath(path, QBrush(Qt.white)) maskPainter.end() mode = QPainter.CompositionMode_SourceIn contentImage = QImage(sz, QImage.Format_ARGB32_Premultiplied) contentPainter = QPainter() contentPainter.begin(contentImage) contentPainter.setCompositionMode(QPainter.CompositionMode_Source) contentPainter.fillRect(contentImage.rect(), Qt.transparent) contentPainter.setCompositionMode(QPainter.CompositionMode_SourceOver) contentPainter.drawImage(0, 0, maskPixmap.toImage()) contentPainter.setCompositionMode(mode) contentPainter.drawImage(0, 0, waterImage) contentPainter.setCompositionMode( QPainter.CompositionMode_DestinationOver) contentPainter.end() contentImage.setDevicePixelRatio(pixelRatio) painter.drawImage(self.rect(), contentImage)
class Segment(QGraphicsItem): ''' # 新建Path QPath 可以通过从empty path或者另一个path新建, Once created, lines and curves can be added to the path using the lineTo(), arcTo(), cubicTo() and quadTo() functions. currentPosition() of the QPainterPath object is always the end position of the last subpath that was added (or the initial start point) # 开始新的subpath的两种方法: moveTo(): function implicitly starts a new subpath, and closes the previous one. closeSubpath():Another way of starting a new subpath is to call the closeSubpath() function which closes the current path by adding a line from the currentPosition() back to the path's start position. Note that the new path will have (0, 0) as its initial currentPosition(). # 一些便捷的方法: addEllipse(), addPath(), addRect(), addRegion() and addText(). The addPolygon() function adds an unclosed subpath. In fact, these functions are all collections of moveTo(), lineTo() and cubicTo() operations. # 连接到上一条Path: In addition, a path can be added to the current path using the connectPath() function. But note that this function will connect the last element of the current path to the first element of given one by adding a line. ''' def __init__(self, color, offset, parent): # offset接收一个偏移量,这是身子相对于头的偏移量 super(Segment, self).__init__(parent) self.color = color self.rect = QRectF(offset, -20, 30, 40) self.path = QPainterPath() self.path.addEllipse(self.rect) x = offset + 15 y = -20 self.path.addPolygon( QPolygonF( [QPointF(x, y), QPointF(x - 5, y - 12), QPointF(x - 5, y)])) self.path.closeSubpath() # Closes the current subpath by drawing a line to the beginning of the subpath, # automatically starting a new path. # The current point of the new path is (0, 0). y = 20 self.path.addPolygon( QPolygonF( [QPointF(x, y), QPointF(x - 5, y + 12), QPointF(x - 5, y)])) self.path.closeSubpath() self.change = 1 self.angle = 0 self.timer = QTimer() self.timer.timeout.connect(self.timeout) self.timer.start(INTERVAL) def boundingRect(self): return self.path.boundingRect() def shape(self): return self.path def paint(self, painter, option, widget=None): painter.setPen(Qt.NoPen) painter.setBrush(QBrush(self.color)) global SCALE martix = SCALE if option.levelOfDetailFromTransform(martix) < 0.9: painter.drawEllipse(self.rect) else: painter.drawPath(self.path) def timeout(self): if not Running: # print("暂停身体生成") return matrix = self.transform() matrix.reset() self.setTransform(matrix) self.angle += self.change if self.angle > 3: self.change = -1 self.angle -= 1 # print("浪过去") elif self.angle < -3: self.change = 1 self.angle += 1 # print("浪回来") self.setRotation(self.angle)
from math import floor # import logging # logger = logging.getLogger(__name__) from PyQt5.QtCore import QPointF, QRectF, Qt from PyQt5.QtGui import QBrush, QPen, QPainterPath, QPolygonF from PyQt5.QtWidgets import QGraphicsItem, QGraphicsPathItem from PyQt5.QtWidgets import QGraphicsRectItem, QGraphicsEllipseItem from cadnano.gui.palette import getColorObj from cadnano.gui.views.pathview import pathstyles as styles _BASE_WIDTH = styles.PATH_BASE_WIDTH PP_L5 = QPainterPath() # Left 5' PainterPath PP_R5 = QPainterPath() # Right 5' PainterPath PP_L3 = QPainterPath() # Left 3' PainterPath PP_R3 = QPainterPath() # Right 3' PainterPath PP_53 = QPainterPath() # Left 5', Right 3' PainterPath PP_35 = QPainterPath() # Left 5', Right 3' PainterPath # set up PP_L5 (left 5' blue square) PP_L5.addRect(0.25 * _BASE_WIDTH, 0.125 * _BASE_WIDTH, 0.75 * _BASE_WIDTH, 0.75 * _BASE_WIDTH) # set up PP_R5 (right 5' blue square) PP_R5.addRect(0, 0.125 * _BASE_WIDTH, 0.75 * _BASE_WIDTH, 0.75 * _BASE_WIDTH) # set up PP_L3 (left 3' blue triangle) L3_POLY = QPolygonF() L3_POLY.append(QPointF(_BASE_WIDTH, 0)) L3_POLY.append(QPointF(0.25 * _BASE_WIDTH, 0.5 * _BASE_WIDTH)) L3_POLY.append(QPointF(_BASE_WIDTH, _BASE_WIDTH))
def _drawGuidelines( painter, glyph, scale, rect, guidelines, drawLines=True, drawText=True, drawSelection=True, color=None, ): if not (drawLines or drawText): return xMin, yMin, width, height = rect xMax = xMin + width yMax = yMin + height for line in guidelines: color_ = color if color_ is None: if line.color: color_ = colorToQColor(line.color) else: color_ = defaultColor("glyphGuideline") painter.save() painter.setPen(color) line1 = None if None not in (line.x, line.y): if line.angle is not None: # make an infinite line that intersects *(line.x, line.y)* # 1. make horizontal line from *(line.x, line.y)* of length # *diagonal* diagonal = math.sqrt(width ** 2 + height ** 2) line1 = QLineF(line.x, line.y, line.x + diagonal, line.y) # 2. set the angle # defcon guidelines are clockwise line1.setAngle(line.angle) # 3. reverse the line and set length to 2 * *diagonal* line1.setPoints(line1.p2(), line1.p1()) line1.setLength(2 * diagonal) else: line1 = QLineF(xMin, line.y, xMax, line.y) textX = 0 textY = 0 if drawLines: if line1 is not None: # line drawLine(painter, line1.x1(), line1.y1(), line1.x2(), line1.y2()) # point x, y = line.x, line.y smoothWidth = 8 * scale smoothHalf = smoothWidth / 2.0 painter.save() pointPath = QPainterPath() x -= smoothHalf y -= smoothHalf pointPath.addEllipse(x, y, smoothWidth, smoothWidth) pen = QPen(color_) pen.setWidthF(1 * scale) painter.setPen(pen) if drawSelection and line.selected: painter.fillPath(pointPath, color_) painter.drawPath(pointPath) painter.restore() else: if line.y is not None: drawLine(painter, xMin, line.y, xMax, line.y) elif line.x is not None: drawLine(painter, line.x, yMin, line.x, yMax) if drawText and line.name: if line1 is not None: textX = line.x textY = line.y - 6 * scale xAlign = "center" else: if line.y is not None: fontSize = painter.font().pointSize() textX = glyph.width + 6 * scale textY = line.y - (fontSize / 3.5) * scale elif line.x is not None: textX = line.x + 6 * scale textY = 0 xAlign = "left" drawTextAtPoint(painter, line.name, textX, textY, scale, xAlign=xAlign) painter.restore()
def paint(self, painter, option, widget): color = Qt.red if self.isSelected() else Qt.black painter.setPen(QPen(color, 2, Qt.SolidLine)) path = QPainterPath(self.startPoint) # start path # iterating over all points of line for i in range(len(self.points) - 1): x1, y1 = self.points[i].x(), self.points[i].y() x2, y2 = self.points[i + 1].x(), self.points[i + 1].y() for point in sorted(self.commonPathsCenters, key=lambda x: x.x() + x.y(), reverse=x2 < x1 or y2 < y1): x, y = point.x(), point.y() if x == x1 == x2: # vertical if min(y1, y2) + 8 <= y < max(y1, y2) - 8: if y2 > y1: path.lineTo(point - QPointF(0, 8)) path.arcTo(QRectF(x - 8, y - 8, 16, 16), 90, -180) path.moveTo(point + QPointF(0, 8)) else: path.lineTo(point + QPointF(0, 8)) path.arcTo(QRectF(x - 8, y - 8, 16, 16), -90, 180) path.moveTo(point - QPointF(0, 8)) elif y == y1 == y2: # horizontal if min(x1, x2) + 8 <= x < max(x1, x2) - 8: if x2 > x1: path.lineTo(point - QPointF(8, 0)) path.arcTo(QRectF(x - 8, y - 8, 16, 16), 180, 180) path.moveTo(point + QPointF(8, 0)) else: path.lineTo(point + QPointF(8, 0)) path.arcTo(QRectF(x - 8, y - 8, 16, 16), 0, -180) path.lineTo(point - QPointF(8, 0)) path.lineTo(self.points[i + 1]) # draw arrow in last segment if i == len(self.points) - 2: arrow_size = 20.0 line = QLineF(self.points[i], self.points[i + 1]) if line.length() < 20: continue angle = math.acos(line.dx() / line.length()) if line.dy() >= 0: angle = (math.pi * 2) - angle arrow_p1 = line.p2() - QPointF(math.sin(angle + math.pi / 2.5) * arrow_size, math.cos(angle + math.pi / 2.5) * arrow_size) arrow_p2 = line.p2() - QPointF(math.sin(angle + math.pi - math.pi / 2.5) * arrow_size, math.cos(angle + math.pi - math.pi / 2.5) * arrow_size) arrowHead = QPolygonF() arrowHead.append(line.p2()) arrowHead.append(arrow_p1) arrowHead.append(arrow_p2) painter.save() painter.setBrush(Qt.black) painter.drawPolygon(arrowHead) painter.restore() painter.drawPath(path) # draw final path
def _paint_utility_blocks(self): scene = self w = scene.width() - (self._left_p + self._right_p) h = scene.height() - (self._top_p + self._bot_p) block_width = self._block_width font = QFont() font.setPointSize(12) font.setBold(True) fm = QFontMetrics(font) # hot utility pen = QPen(Qt.red, 5, Qt.SolidLine, Qt.SquareCap, Qt.RoundJoin) path = QPainterPath() path.addRoundedRect(0, 0, block_width, h, 10, 10) path = scene.addPath(path, pen=pen) path.setPos(self._map_x(0), self._map_y(h)) text = scene.addText("Hot Utility", font=font) text.setDefaultTextColor(Qt.red) t_wid = fm.horizontalAdvance(text.toPlainText()) text.setPos( self._map_x((block_width - fm.height()) / 2), self._map_y((h - t_wid) / 2) ) text.setRotation(-90.0) # cold utility pen = QPen(Qt.blue, 5, Qt.SolidLine, Qt.SquareCap, Qt.RoundJoin) path = QPainterPath() path.addRoundedRect(0, 0, block_width, h, 10, 10) path = scene.addPath(path, pen=pen) path.setPos(self._map_x(w - block_width), self._map_y(h)) text = scene.addText("Cold Utility", font=font) text.setDefaultTextColor(Qt.blue) t_wid = fm.horizontalAdvance(text.toPlainText()) text.setPos( self._map_x(w - (block_width + fm.height()) / 2), self._map_y((h - t_wid) / 2) ) text.setRotation(-90.0)
def drawGlyphPoints( painter, glyph, scale, drawStartPoints=True, drawOnCurves=True, drawOffCurves=True, drawCoordinates=False, drawHandleCoordinates=False, drawCoordinatesOnSelection=False, drawSelection=True, drawBluesMarkers=True, onCurveColor=None, onCurveSmoothColor=None, offCurveColor=None, otherColor=None, backgroundColor=None, ): if onCurveColor is None: onCurveColor = defaultColor("glyphOnCurvePoints") if onCurveSmoothColor is None: onCurveSmoothColor = defaultColor("glyphOnCurveSmoothPoints") if offCurveColor is None: offCurveColor = defaultColor("glyphOffCurvePoints") if otherColor is None: otherColor = defaultColor("glyphOtherPoints") if backgroundColor is None: backgroundColor = defaultColor("background") bluesMarkerColor = defaultColor("glyphBluesMarker") notchColor = defaultColor("glyphContourStroke").lighter(200) # get the outline data outlineData = glyph.getRepresentation("defconQt.OutlineInformation") points = [] handles = [] # blue zones markers if drawBluesMarkers and drawOnCurves: font = glyph.font blues = [] if font.info.postscriptBlueValues: blues += font.info.postscriptBlueValues if font.info.postscriptOtherBlues: blues += font.info.postscriptOtherBlues if blues: blues_ = set(blues) size = 13 * scale selectedSize = 15 * scale snapSize = 17 * scale selectedSnapSize = 20 * scale painter.save() pen = painter.pen() pen.setColor(QColor(255, 255, 255, 125)) pen.setWidth(0) painter.setPen(pen) for point in outlineData["onCurvePoints"]: x, y = point["point"] # TODO: we could add a non-overlapping interval tree special # cased for borders selected = drawSelection and point.get("selected", False) if selected: size_ = selectedSize snapSize_ = selectedSnapSize else: size_ = size snapSize_ = snapSize for yMin, yMax in zip(blues[::2], blues[1::2]): if not (y >= yMin and y <= yMax): continue # if yMin > 0 and y == yMin or yMin <= 0 and y == yMax: if y in blues_: path = lozengePath(x, y, snapSize_) else: path = ellipsePath(x, y, size_) painter.fillPath(path, bluesMarkerColor) painter.drawPath(path) painter.restore() # handles if drawOffCurves and outlineData["offCurvePoints"]: painter.save() painter.setPen(otherColor) for x1, y1, x2, y2 in outlineData["bezierHandles"]: handles.append((x2, y2)) drawLine(painter, x1, y1, x2, y2) painter.restore() # on curve if drawOnCurves and outlineData["onCurvePoints"]: size = 6.5 * scale selectedSize = 8.5 * scale smoothSize = 8 * scale selectedSmoothSize = 10 * scale startSize = 7 * scale selectedStartSize = 9 * scale loneStartSize = 12 * scale selectedLoneStartSize = 14 * scale painter.save() notchPath = QPainterPath() paths = (QPainterPath(), QPainterPath()) smoothPaths = (QPainterPath(), QPainterPath()) for point in outlineData["onCurvePoints"]: x, y = point["point"] points.append((x, y)) # notch if "smoothAngle" in point: angle = point["smoothAngle"] t = Identity.rotate(angle) x1, y1 = t.transformPoint((-1.35 * scale, 0)) x2, y2 = -x1, -y1 x1 += x y1 += y x2 += x y2 += y notchPath.moveTo(x1, y1) notchPath.lineTo(x2, y2) # points selected = drawSelection and point.get("selected", False) if selected: size_ = selectedSize smoothSize_ = selectedSmoothSize startSize_ = selectedStartSize loneStartSize_ = selectedLoneStartSize else: size_ = size smoothSize_ = smoothSize startSize_ = startSize loneStartSize_ = loneStartSize if drawStartPoints and "startPointAngle" in point: angle = point["startPointAngle"] if angle is not None: pointPath = trianglePath(x, y, startSize_, angle) else: pointPath = ellipsePath(x, y, loneStartSize_) elif point["smooth"]: pointPath = ellipsePath(x, y, smoothSize_) else: pointPath = rectanglePath(x, y, size_) # store the path if point["smooth"]: smoothPaths[selected].addPath(pointPath) else: paths[selected].addPath(pointPath) if drawCoordinatesOnSelection and selected and not drawCoordinates: drawPointText(painter, x, y, scale, ishandle=False) path, selectedPath = paths smoothPath, selectedSmoothPath = smoothPaths # fill selectedPath.setFillRule(Qt.WindingFill) selectedSmoothPath.setFillRule(Qt.WindingFill) painter.fillPath(selectedPath, onCurveColor) painter.fillPath(selectedSmoothPath, onCurveSmoothColor) # stroke pen = QPen(onCurveColor) pen.setWidthF(1.2 * scale) painter.setPen(pen) painter.drawPath(path) pen.setColor(onCurveSmoothColor) painter.setPen(pen) painter.drawPath(smoothPath) # notch pen.setColor(notchColor) pen.setWidth(0) painter.setPen(pen) painter.drawPath(notchPath) painter.restore() # off curve if drawOffCurves and outlineData["offCurvePoints"]: # points offSize = 4.25 * scale selectedOffSize = 6.75 * scale path = QPainterPath() selectedPath = QPainterPath() selectedPath.setFillRule(Qt.WindingFill) for point in outlineData["offCurvePoints"]: x, y = point["point"] selected = drawSelection and point.get("selected", False) if selected: offSize_ = selectedOffSize else: offSize_ = offSize pointPath = ellipsePath(x, y, offSize_) if selected: selectedPath.addPath(pointPath) else: path.addPath(pointPath) if drawCoordinatesOnSelection and selected and not drawHandleCoordinates: drawPointText(painter, x, y, scale, ishandle=True) pen = QPen(offCurveColor) pen.setWidthF(2.5 * scale) painter.save() painter.setPen(pen) painter.drawPath(path) painter.fillPath(path, QBrush(backgroundColor)) painter.fillPath(selectedPath, QBrush(offCurveColor.lighter(135))) painter.restore() # coordinates if drawCoordinates: painter.save() for x, y in points: drawPointText(painter, x, y, scale, ishandle=False) painter.restore() # handle coordinates if drawHandleCoordinates: painter.save() for x, y in handles: drawPointText(painter, x, y, scale, ishandle=True) painter.restore()
def showWedge(self, angle, color, extended=False, rev_gradient=False, outline_only=False): """Summary Args: angle (TYPE): Description color (TYPE): Description extended (bool, optional): Description rev_gradient (bool, optional): Description outline_only (bool, optional): Description """ # Hack to keep wedge in front # self.setRotation(self.pre_xover_item_group.rotation()) self._last_params = (angle, color, extended, rev_gradient, outline_only) radius = self._radius span = self.pre_xover_item_group.partCrossoverSpanAngle() / 2 radius_adjusted = radius + (_WEDGE_RECT_GAIN / 2) tip = QPointF(radius_adjusted, radius_adjusted) EXT = 1.35 if extended else 1.0 # print("wtf", tip, pos) base_p2 = QPointF(1, 1) line0 = QLineF(tip, QPointF(base_p2)) line1 = QLineF(tip, QPointF(base_p2)) line2 = QLineF(tip, QPointF(base_p2)) quad_scale = 1 + (.22*(span - 5) / 55) # lo+(hi-lo)*(val-min)/(max-min) line0.setLength(radius_adjusted * EXT*quad_scale) # for quadTo control point line1.setLength(radius_adjusted * EXT) line2.setLength(radius_adjusted * EXT) line0.setAngle(angle) line1.setAngle(angle - span) line2.setAngle(angle + span) path = QPainterPath() if outline_only: self.setPen(getPenObj(color, 0.5, alpha=128, capstyle=Qt.RoundCap)) path.moveTo(line1.p2()) path.quadTo(line0.p2(), line2.p2()) else: gradient = QRadialGradient(tip, radius_adjusted * EXT) color1 = getColorObj(color, alpha=80) color2 = getColorObj(color, alpha=0) if rev_gradient: color1, color2 = color2, color1 if extended: gradient.setColorAt(0, color1) gradient.setColorAt(radius_adjusted / (radius_adjusted * EXT), color1) gradient.setColorAt(radius_adjusted / (radius_adjusted * EXT) + 0.01, color2) gradient.setColorAt(1, color2) else: gradient.setColorAt(0, getColorObj(color, alpha=50)) brush = QBrush(gradient) self.setBrush(brush) path.moveTo(line1.p1()) path.lineTo(line1.p2()) path.quadTo(line0.p2(), line2.p2()) path.lineTo(line2.p1()) self.setPath(path) self.show()
def __init__(self): super(Window, self).__init__() rectPath = QPainterPath() rectPath.moveTo(20.0, 30.0) rectPath.lineTo(80.0, 30.0) rectPath.lineTo(80.0, 70.0) rectPath.lineTo(20.0, 70.0) rectPath.closeSubpath() roundRectPath = QPainterPath() roundRectPath.moveTo(80.0, 35.0) roundRectPath.arcTo(70.0, 30.0, 10.0, 10.0, 0.0, 90.0) roundRectPath.lineTo(25.0, 30.0) roundRectPath.arcTo(20.0, 30.0, 10.0, 10.0, 90.0, 90.0) roundRectPath.lineTo(20.0, 65.0) roundRectPath.arcTo(20.0, 60.0, 10.0, 10.0, 180.0, 90.0) roundRectPath.lineTo(75.0, 70.0) roundRectPath.arcTo(70.0, 60.0, 10.0, 10.0, 270.0, 90.0) roundRectPath.closeSubpath() ellipsePath = QPainterPath() ellipsePath.moveTo(80.0, 50.0) ellipsePath.arcTo(20.0, 30.0, 60.0, 40.0, 0.0, 360.0) piePath = QPainterPath() piePath.moveTo(50.0, 50.0) piePath.lineTo(65.0, 32.6795) piePath.arcTo(20.0, 30.0, 60.0, 40.0, 60.0, 240.0) piePath.closeSubpath() polygonPath = QPainterPath() polygonPath.moveTo(10.0, 80.0) polygonPath.lineTo(20.0, 10.0) polygonPath.lineTo(80.0, 30.0) polygonPath.lineTo(90.0, 70.0) polygonPath.closeSubpath() groupPath = QPainterPath() groupPath.moveTo(60.0, 40.0) groupPath.arcTo(20.0, 20.0, 40.0, 40.0, 0.0, 360.0) groupPath.moveTo(40.0, 40.0) groupPath.lineTo(40.0, 80.0) groupPath.lineTo(80.0, 80.0) groupPath.lineTo(80.0, 40.0) groupPath.closeSubpath() textPath = QPainterPath() timesFont = QFont("Times", 50) timesFont.setStyleStrategy(QFont.ForceOutline) textPath.addText(10, 70, timesFont, "Qt") bezierPath = QPainterPath() bezierPath.moveTo(20, 30) bezierPath.cubicTo(80, 0, 50, 50, 80, 80) starPath = QPainterPath() starPath.moveTo(90, 50) for i in range(1, 5): starPath.lineTo(50 + 40 * cos(0.8 * i * pi), 50 + 40 * sin(0.8 * i * pi)) starPath.closeSubpath() self.renderAreas = [ RenderArea(rectPath), RenderArea(roundRectPath), RenderArea(ellipsePath), RenderArea(piePath), RenderArea(polygonPath), RenderArea(groupPath), RenderArea(textPath), RenderArea(bezierPath), RenderArea(starPath), ] assert len(self.renderAreas) == 9 self.fillRuleComboBox = QComboBox() self.fillRuleComboBox.addItem("Odd Even", Qt.OddEvenFill) self.fillRuleComboBox.addItem("Winding", Qt.WindingFill) fillRuleLabel = QLabel("Fill &Rule:") fillRuleLabel.setBuddy(self.fillRuleComboBox) self.fillColor1ComboBox = QComboBox() self.populateWithColors(self.fillColor1ComboBox) self.fillColor1ComboBox.setCurrentIndex( self.fillColor1ComboBox.findText("mediumslateblue")) self.fillColor2ComboBox = QComboBox() self.populateWithColors(self.fillColor2ComboBox) self.fillColor2ComboBox.setCurrentIndex( self.fillColor2ComboBox.findText("cornsilk")) fillGradientLabel = QLabel("&Fill Gradient:") fillGradientLabel.setBuddy(self.fillColor1ComboBox) fillToLabel = QLabel("to") fillToLabel.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.penWidthSpinBox = QSpinBox() self.penWidthSpinBox.setRange(0, 20) penWidthLabel = QLabel("&Pen Width:") penWidthLabel.setBuddy(self.penWidthSpinBox) self.penColorComboBox = QComboBox() self.populateWithColors(self.penColorComboBox) self.penColorComboBox.setCurrentIndex( self.penColorComboBox.findText("darkslateblue")) penColorLabel = QLabel("Pen &Color:") penColorLabel.setBuddy(self.penColorComboBox) self.rotationAngleSpinBox = QSpinBox() self.rotationAngleSpinBox.setRange(0, 359) self.rotationAngleSpinBox.setWrapping(True) self.rotationAngleSpinBox.setSuffix(u"\N{DEGREE SIGN}") rotationAngleLabel = QLabel("&Rotation Angle:") rotationAngleLabel.setBuddy(self.rotationAngleSpinBox) self.fillRuleComboBox.activated.connect(self.fillRuleChanged) self.fillColor1ComboBox.activated.connect(self.fillGradientChanged) self.fillColor2ComboBox.activated.connect(self.fillGradientChanged) self.penColorComboBox.activated.connect(self.penColorChanged) for i in range(Window.NumRenderAreas): self.penWidthSpinBox.valueChanged.connect( self.renderAreas[i].setPenWidth) self.rotationAngleSpinBox.valueChanged.connect( self.renderAreas[i].setRotationAngle) topLayout = QGridLayout() for i in range(Window.NumRenderAreas): topLayout.addWidget(self.renderAreas[i], i / 3, i % 3) mainLayout = QGridLayout() mainLayout.addLayout(topLayout, 0, 0, 1, 4) mainLayout.addWidget(fillRuleLabel, 1, 0) mainLayout.addWidget(self.fillRuleComboBox, 1, 1, 1, 3) mainLayout.addWidget(fillGradientLabel, 2, 0) mainLayout.addWidget(self.fillColor1ComboBox, 2, 1) mainLayout.addWidget(fillToLabel, 2, 2) mainLayout.addWidget(self.fillColor2ComboBox, 2, 3) mainLayout.addWidget(penWidthLabel, 3, 0) mainLayout.addWidget(self.penWidthSpinBox, 3, 1, 1, 3) mainLayout.addWidget(penColorLabel, 4, 0) mainLayout.addWidget(self.penColorComboBox, 4, 1, 1, 3) mainLayout.addWidget(rotationAngleLabel, 5, 0) mainLayout.addWidget(self.rotationAngleSpinBox, 5, 1, 1, 3) self.setLayout(mainLayout) self.fillRuleChanged() self.fillGradientChanged() self.penColorChanged() self.penWidthSpinBox.setValue(2) self.setWindowTitle("Painter Paths")
def setup(self): p = QPainterPath() p.addEllipse(-NW / 2, -NW / 2, NW, NW) self.setPath(p)