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 setIsOutput(self, isOutput): self.isOutput_ = isOutput path = QPainterPath() if self.isOutput_: if self.name == '': path.addRect(-2 * self.radius_, -self.radius_, 2 * self.radius_, 2 * self.radius_) self.label.setPos( -self.radius_ - self.margin - self.label.boundingRect().width(), -self.label.boundingRect().height() / 2) else: path.addEllipse(-2 * self.radius_, -self.radius_, 2 * self.radius_, 2 * self.radius_) self.label.setPos( -self.radius_ - self.margin - self.label.boundingRect().width(), -self.label.boundingRect().height() / 2) else: if self.name == '': path.addRect(0, -self.radius_, 2 * self.radius_, 2 * self.radius_) self.label.setPos(self.radius_ + self.margin, -self.label.boundingRect().height() / 2) else: path.addEllipse(0, -self.radius_, 2 * self.radius_, 2 * self.radius_) self.label.setPos(self.radius_ + self.margin, -self.label.boundingRect().height() / 2) self.setPath(path)
def getBgPainterPath(self): path = QPainterPath() w = self.size().width() h = self.size().height() rect = QRectF(w/2-self.radius, h/2-self.radius, self.radius*2, self.radius*2) path.addEllipse(rect) return path
def pathForPointR(self, p, scene, rsize=5): t = scene.views()[0].transform() rx, ry = rsize / t.m11(), rsize / t.m22() #lst = self.listOfCirclePoints(p, rx, ry, np=12) path = QPainterPath() path.addEllipse(p, rx, ry) return path
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 _pointWithinThreshold(x, y, curve, eps): """ See whether *(x, y)* is within *eps* of *curve*. """ path = QPainterPath() path.addEllipse(x - eps, y - eps, 2 * eps, 2 * eps) curvePath = QPainterPath() if curve[-1].segmentType == "curve": p1, p2, p3, p4 = curve curvePath.moveTo(p1.x, p1.y) curvePath.cubicTo(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y) curvePath.cubicTo(p3.x, p3.y, p2.x, p2.y, p1.x, p1.y) else: first = curve[0] curvePath.moveTo(first.x, first.y) # PACK for fontTools pts = [] for pt in curve: pts.append((pt.x, pt.y)) # draw for pt1, pt2 in decomposeQuadraticSegment(pts[1:]): curvePath.quadTo(*pt1+pt2) for pt1, pt2 in decomposeQuadraticSegment(list(reversed(pts[:-1]))): curvePath.quadTo(*pt1+pt2) return path.intersects(curvePath)
def _pointWithinThreshold(x, y, curve, eps): """ See whether *(x, y)* is within *eps* of *curve*. """ path = QPainterPath() path.addEllipse(x - eps, y - eps, 2 * eps, 2 * eps) curvePath = QPainterPath() if curve[-1].segmentType == "curve": p1, p2, p3, p4 = curve curvePath.moveTo(p1.x, p1.y) curvePath.cubicTo(p2.x, p2.y, p3.x, p3.y, p4.x, p4.y) curvePath.cubicTo(p3.x, p3.y, p2.x, p2.y, p1.x, p1.y) else: first = curve[0] curvePath.moveTo(first.x, first.y) # PACK for fontTools pts = [] for pt in curve: pts.append((pt.x, pt.y)) # draw for pt1, pt2 in decomposeQuadraticSegment(pts[1:]): curvePath.quadTo(*pt1 + pt2) for pt1, pt2 in decomposeQuadraticSegment(list(reversed(pts[:-1]))): curvePath.quadTo(*pt1 + pt2) return path.intersects(curvePath)
class RoundAnimation(QPropertyAnimation): def __init__(self, target, prop, parent=None): super(RoundAnimation, self).__init__(target, prop, parent) def updateCurrentTime(self, currentTime): self.path = QPainterPath() if self.path.isEmpty(): end = self.endValue() start = self.startValue() self.path.addEllipse(QRectF(start, end)) duration = self.duration() if duration == 0: progress = 1.0 else: progress = (((currentTime - 1) % duration) + 1) / float(duration) easedProgress = self.easingCurve().valueForProgress(progress) if easedProgress > 1.0: easedProgress -= 1.0 elif easedProgress < 0: easedProgress += 1.0 pt = self.path.pointAtPercent(easedProgress) self.updateCurrentValue(pt)
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)
class My_gripItem(QGraphicsPathItem): def __init__(self, annotation_item, index, type=0): super(My_gripItem, self).__init__() self.m_annotation_item = annotation_item self.m_index = index self.circle = QPainterPath() self.circle.addEllipse(QRectF(-4, -4, 8, 8)) self.square = QPainterPath() self.square.addRect(QRectF(-4, -4, 8, 8)) self.setPath(self.circle) self.setBrush(Qt.green) self.setFlag(QGraphicsItem.ItemIsSelectable, True) if type == 1: self.setFlag(QGraphicsItem.ItemIsMovable, True) self.setFlag(QGraphicsItem.ItemSendsGeometryChanges, True) self.setFlag(QGraphicsItem.ItemIgnoresTransformations) self.setAcceptHoverEvents(True) self.setZValue(11) self.setCursor(QCursor(Qt.PointingHandCursor)) def hoverEnterEvent(self, event): self.setPath(self.square) self.setBrush(Qt.red) super(My_gripItem, self).hoverEnterEvent(event) def hoverLeaveEvent(self, event): self.setPath(self.circle) self.setBrush(Qt.green) super(My_gripItem, self).hoverLeaveEvent(event) def itemChange(self, change, value): if change == QGraphicsItem.ItemPositionChange and self.isEnabled(): self.m_annotation_item.movePoint(self.m_index, value) return super(My_gripItem, self).itemChange(change, value)
def render_avatar_image(image: QImage, size: float): if image.isNull(): return None aspect_ratio = image.width() / image.height() if aspect_ratio > 1: width = size height = size / aspect_ratio else: width = size * aspect_ratio height = size x0 = (size - width) / 2 y0 = (size - height) / 2 path = QPainterPath() path.addEllipse(QRectF(x0, y0, width, height)) picture = QPicture() painter = QPainter(picture) painter.setRenderHint(QPainter.Antialiasing, True) pen = QPen(Qt.black, 5) pen.setStyle(Qt.SolidLine) painter.setPen(pen) painter.setClipPath(path) painter.drawImage( QRectF(x0, y0, width, height), image, ) painter.end() return picture
def pathForPointR(self, p, scene, rsize=5): """ point shape - Ellipse """ rx, ry = self.size_on_scene(scene, rsize) path = QPainterPath() path.addEllipse(p, rx, ry) return path
def draw_bg(self, qp, rect, text): path = QPainterPath() # add container path.addRoundedRect(rect, 4, 4) if self.isEnabled(): highlight_color, bg_color, text_color = ( self.settings['highlight'], self.settings['bg'], self.settings['text']) else: highlight_color, bg_color, text_color = ( self.settings['highlight_disabled'], self.settings['bg_disabled'], self.settings['text_disabled']) qp.setPen(QPen(highlight_color, 2)) qp.fillPath(path, bg_color) # add close button circle_size = rect.height() / 1.8 pen_size = 2 qp.setPen(QPen(text_color, pen_size, Qt.SolidLine)) rect = QRectF( rect.right() - circle_size - self.settings['padding-x'] / 2, rect.top() + (rect.height() - circle_size) / 2, circle_size, circle_size) path.addEllipse(rect) qp.drawPath(path) # draw cross inside_rect = QRectF(rect) inside_rect.adjust(pen_size, pen_size, -pen_size, -pen_size) qp.drawLine(inside_rect.topLeft(), inside_rect.bottomRight()) qp.drawLine(inside_rect.bottomLeft(), inside_rect.topRight()) self.close_rectangles[text] = rect
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, e): painter = QtGui.QPainter(self) painter.setPen(QtCore.Qt.NoPen) painter.setRenderHint(QtGui.QPainter.Antialiasing) if self.model: self.agentimage.fill(QColor(0, 0, 0, 0)) select = None for agent in self.model.agents: self.paintAgent(painter, agent) if agent.selected: select = agent if select: path = QPainterPath() path.addRect(0, 0, self.model.width, self.model.height) path.addEllipse( select.x - select.size * 1.5, select.y - select.size * 1.5, select.size * 3, select.size * 3, ) painter.setBrush(QColor(0, 0, 0, 150)) painter.drawPath(path) painter.end()
def shape(self): """ Returns the shape of this item as a QPainterPath in local coordinates. :rtype: QPainterPath """ path = QPainterPath() path.addEllipse(self.polygon) return path
def shape(self): """Возвращает форму этого элемента в виде QPainterPath в локальных координатах.""" 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.addEllipse(self.polygon) return path
def roboShape(self): shape = QPainterPath() shape.addEllipse(int(round(self.position.x())), int(round(self.position.y())), self.radius, self.radius) return shape
class Segment(QGraphicsItem): def __init__(self, color, offset, parent): 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 - 18), QPointF(x - 5, y)])) self.path.closeSubpath() # 每节的右腿 y = 20 self.path.addPolygon( QPolygonF( [QPointF(x, y), QPointF(x - 5, y + 18), QPointF(x - 5, y)])) self.path.closeSubpath() self.change = 1 self.angle = 0 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)) if option.levelOfDetailFromTransform(self.transform()) < 0.9: painter.drawEllipse(self.rect) else: painter.drawPath(self.path) def advance(self, phase): if phase == 0: matrix = self.transform() matrix.reset() self.setTransform(matrix) self.angle += self.change * random.random() if self.angle > 6: self.change = -1 # self.angle -= 0.00001 elif self.angle < -6: self.change = 1 # self.angle += 0.00001 elif phase == 1: self.setRotation(self.angle)
def __init__(self, center_point, radius): self.__figure_type = "CIRCLE" self.__center_point = center_point self.__radius = radius path = QPainterPath() path.addEllipse(center_point, radius, radius) super().__init__(path)
def getWaterPainterPath(self, water): circle = QRectF( water.point.x() - self.water_radius * water.progress / 100, water.point.y() - self.water_radius * water.progress / 100, self.water_radius * water.progress / 50, self.water_radius * water.progress / 50) path = QPainterPath() path.addEllipse(circle) return path & self.getBgPainterPath()
class Segment(QGraphicsItem): def __init__(self, color, offset, parent): 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() 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)) if option.levelOfDetailFromTransform(self.transform()) < 0.9: painter.drawEllipse(self.rect) else: painter.drawPath(self.path) def timeout(self): if not Running: return matrix = self.transform() matrix.reset() self.setTransform(matrix) self.angle += self.change * random.random() if self.angle > 4.5: self.change = -1 self.angle -= 0.00001 elif self.angle < -4.5: self.change = 1 self.angle += 0.00001 self.setRotation(self.angle)
def paint(self, painter, index): widget = self.parent() if index != widget.activeIndex(): return scale = widget.inverseScale() # metrics if self._rulerObject is not None: line, a = self._rulerObject origin = line.p1() cursor = line.p2() size = 8 * scale halfSize = 4 * scale color = QColor(255, 85, 127, 170) # line painter.save() painter.setPen(color) drawing.drawLine(painter, origin.x(), origin.y(), cursor.x(), cursor.y(), scale) # ellipses ellipses = [ (origin.x(), origin.y()), (cursor.x(), cursor.y()), ] path = QPainterPath() path.setFillRule(Qt.WindingFill) for x, y in itertools.chain(self._rulerPts.values(), ellipses): x -= halfSize y -= halfSize path.addEllipse(x, y, size, size) painter.fillPath(path, color) painter.restore() # text line = QLineF(line) xAlign = yAlign = "center" ellipses.pop(0) rp = self._rulerPts # XXX: sort shouldn't be performed in paintEvent for pt in itertools.chain((rp[k] for k in sorted(rp)), ellipses): p = QPointF(*pt) line.setP2(p) if line.length(): d = str(round(line.length(), 1)) pos = (line.p1() + line.p2()) / 2 drawing.drawTextAtPoint(painter, d, pos.x(), pos.y(), scale, xAlign, yAlign) line.setP1(p) xAlign, yAlign = "left", "top" dx = cursor.x() - origin.x() px = size if dx < 0: xAlign = "right" px = -px drawing.drawTextAtPoint(painter, a, cursor.x() + px, cursor.y() + size, scale, xAlign, yAlign)
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 eraser_action(self, pos: QPoint): pos = self.mapToScene(pos) path = QPainterPath() path.addEllipse(QPoint(0, 0), self._eraser_size, self._eraser_size) eraser_area = SelectionItem(pos, path=path, view_scale=1, scene=self.scene()) eraser_area.setVisible(False) self.eraser_action_signal.emit(eraser_area)
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 setShapeRect(self, rect): """ Set the item's shape `rect`. The item should be confined within this rect. """ path = QPainterPath() path.addEllipse(rect) self.setPath(path) self.__shapeRect = rect
def shape(self): """ Returns the shape of this item as a QPainterPath in local coordinates. :rtype: QPainterPath """ path = QPainterPath() path.addPolygon(self.polygon) for shape in self.handleBound: path.addEllipse(shape) return path
def shape(self): #QPainterPath为绘图操作提供了一个容器,为图形形状的构造和重用提供了一种方式 # 初始化方法 #addEllipse (self, QRectF rect) #addEllipse (self, float x, float y, float w, float h) #addEllipse (self, QPointF center, float rx, float ry) path = QPainterPath() path.addEllipse(self.boundingRect()) return path
def _dbgRingShape(self, p): r, R, = self.boundings() opath = QPainterPath() opath.setFillRule(Qt.WindingFill) opath.addEllipse(-R, -R, 2*R, 2*R) ipath = QPainterPath() ipath.setFillRule(Qt.WindingFill) ipath.addEllipse(-r, -r, 2*r, 2*r) p.fillPath(opath.subtracted(ipath), QColor(255, 255, 0, 50)) p.strokePath(opath.simplified(), QPen(Qt.black, 3)) p.strokePath(ipath, QPen(Qt.black, 1))
class Animation(QPropertyAnimation): ''' 动画类 ''' def __init__(self, target, prop): ''' target, prop这个两个参数分别对应:动画的产生对象和setter ''' super(Animation, self).__init__(target, prop) def updateCurrentTime(self, currentTime): ''' currentTime(此属性保存动画的当前时间和进度)总是在变化的。 每次动画的currentTime更改时,都会调用updateCurrentTime()函数 ''' self.m_path = QPainterPath() if self.m_path.isEmpty(): end = self.endValue() start = self.startValue() # endValue()、startValue()分别表示动画的结束值和起始值 self.m_path.addEllipse(QRectF(start, end)) # 在指定的boundingRectangle内创建一个椭圆,这里是QRectF(start, end),并将其作为封闭的子路径添加到painter路径中。 dura = self.duration() progress = (((currentTime - 1) % dura) + 1) / float(dura) # duration()此属性保存动画的持续时间(以毫秒为单位)。 默认持续时间为250毫秒。progress则描绘了当前的完成比率。 easedProgress = self.easingCurve().valueForProgress(progress) if easedProgress > 1.0: easedProgress -= 1.0 elif easedProgress < 0: easedProgress += 1.0 # 返回进度缓和曲线的有效进度。 进度必须介于0和1之间,而返回的有效进度可能超出这些范围。大于1就减1,小于0就加1。 pt = self.m_path.pointAtPercent(easedProgress) # 返回当前路径的百分比easedProgress处的点。 # 参数easedProgress必须介于0和1之间。当存在曲线时,百分比参数被映射到贝塞尔方程的t参数。 self.updateCurrentValue(pt) # 每次动画的当前值更改时,都会调用updateCurrentValue()。pt参数是新的当前值。没有这个函数动画动不了。 self.valueChanged.emit(pt) def startAnimation(self, startx, starty, endx, endy, duration): ''' setStartValue()、setEndValue()分别表示设置动画的起止位置,setDuration()设置动画的运行时间。 ''' self.setStartValue(QPointF(startx, starty)) self.setEndValue(QPointF(endx, endy)) self.setDuration(duration) self.setLoopCount(-1) # 值为-1时,动画将永远循环直至停止 self.start()
def drawMagnifierOnVideo(width, height, maskPixmap, dragPos, zoomPixmap, surface, painter, offset): ''' Draw Magnifier on Video ''' dim = min(width, height) MAX_MAGNIFIER = 229 magnifierSize = min(MAX_MAGNIFIER, dim * 2 / 3) radius = magnifierSize / 2 ring = radius - 15 box = QSize(magnifierSize, magnifierSize) # reupdate our mask if maskPixmap.size() != box: maskPixmap = QPixmap(box) 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(maskPixmap) mask.setRenderHint(QPainter.HighQualityAntialiasing) mask.setCompositionMode(QPainter.CompositionMode_Source) mask.setBrush(g) mask.setPen(Qt.NoPen) mask.drawRect(maskPixmap.rect()) mask.setBrush(QColor(Qt.transparent)) mask.drawEllipse(g.center(), ring, ring) mask.end() center = 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 zoomPixmap.size() != box: zoomPixmap = QPixmap(box) zoomPixmap.fill(Qt.lightGray) if True: painter_p = QPainter(zoomPixmap) painter_p.translate(-xy) largePixmap = QPixmap.fromImage(surface.image) painter_p.drawPixmap(offset, largePixmap) painter_p.end() clipPath = QPainterPath() clipPath.addEllipse(QPointF(center), ring, ring) painter.setClipPath(clipPath) painter.drawPixmap(corner, zoomPixmap) painter.setClipping(False) painter.drawPixmap(corner, maskPixmap) painter.setPen(Qt.gray) painter.drawPath(clipPath) return
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 shape(self) -> QPainterPath: rect = self.rect() path = QPainterPath() stroker = QPainterPathStroker() path.addEllipse(rect) stroker.setWidth(self.pen().width()) if self.isSelected(): path.addRect(QRectF(rect.topLeft(), QSizeF(5., 5.))) path.addRect(QRectF(rect.topRight() - QPointF(5., 0.), QSizeF(5., 5.))) path.addRect(QRectF(rect.bottomLeft() - QPointF(0., 5.), QSizeF(5., 5.))) path.addRect(QRectF(rect.bottomRight() - QPointF(5., 5.), QSizeF(5., 5.))) return stroker.createStroke(path)
class _MoveAnimation(QPropertyAnimation): '''move animation''' MOVE1 = 1 MOVE2 = 2 MOVE3 = 3 def __init__(self, target, parent, easing=QEasingCurve.Custom): super(_MoveAnimation, self).__init__(target, b"pos") self.parent = parent self.easing = easing if easing != -1: self.setEasingCurve(easing) self.m_path = QPainterPath() def setMoveType(self, _type): self._type = _type def updateCurrentTime(self, currentTime): if self.m_path.isEmpty(): # end = self.endValue() start = self.startValue() if self._type == self.MOVE1: end = QPoint(self.parent.width() / 4.0, 0) elif self._type == self.MOVE2: end = QPoint((self.parent.width() / 4.0) * 3.0, 0) if not start: start = QPoint(self.parent.width() / 4.0, 0) # 第二个移动没有设置开始坐标,这里以第一个移动结束为开始 elif self._type == self.MOVE3: if not start: start = QPoint((self.parent.width() / 4.0) * 3.0, 0) # 第三个移动没有设置开始坐标,这里以第二个移动结束为开始 end = QPoint(self.parent.width(), 0) self.m_path.moveTo(start) self.m_path.addEllipse(QRectF(start, end)) dura = self.duration() if dura == 0: progress = 1.0 else: progress = (((currentTime - 1) % dura) + 1) / float(dura) easedProgress = self.easingCurve().valueForProgress(progress) if easedProgress > 1.0: easedProgress -= 1.0 elif easedProgress < 0: easedProgress += 1.0 pt = self.m_path.pointAtPercent(easedProgress) self.updateCurrentValue(pt) self.valueChanged.emit(pt) super(_MoveAnimation, self).updateCurrentTime(currentTime)
class _MoveAnimation(QPropertyAnimation): '''move animation''' MOVE1 = 1 MOVE2 = 2 MOVE3 = 3 def __init__(self, target, parent, easing = QEasingCurve.Custom): super(_MoveAnimation, self).__init__(target, b"pos") self.parent = parent self.easing = easing if easing != -1: self.setEasingCurve(easing) self.m_path = QPainterPath() def setMoveType(self, _type): self._type = _type def updateCurrentTime(self, currentTime): if self.m_path.isEmpty(): # end = self.endValue() start = self.startValue() if self._type == self.MOVE1: end = QPoint(self.parent.width() / 4.0, 0) elif self._type == self.MOVE2: end = QPoint((self.parent.width() / 4.0) * 3.0, 0) if not start: start = QPoint(self.parent.width() / 4.0, 0) # 第二个移动没有设置开始坐标,这里以第一个移动结束为开始 elif self._type == self.MOVE3: if not start: start = QPoint((self.parent.width() / 4.0) * 3.0, 0) # 第三个移动没有设置开始坐标,这里以第二个移动结束为开始 end = QPoint(self.parent.width(), 0) self.m_path.moveTo(start) self.m_path.addEllipse(QRectF(start, end)) dura = self.duration() if dura == 0: progress = 1.0 else: progress = (((currentTime - 1) % dura) + 1) / float(dura) easedProgress = self.easingCurve().valueForProgress(progress) if easedProgress > 1.0: easedProgress -= 1.0 elif easedProgress < 0: easedProgress += 1.0 pt = self.m_path.pointAtPercent(easedProgress) self.updateCurrentValue(pt) self.valueChanged.emit(pt) super(_MoveAnimation, self).updateCurrentTime(currentTime)
def boundingRect(self): """ Returns the shape bounding rect. :rtype: QRectF """ path = QPainterPath() path.addPath(self.selection) path.addPolygon(self.head) for shape in self.handles: path.addEllipse(shape) for shape in self.anchors.values(): path.addEllipse(shape) return path.controlPointRect()
def shape(self): """ Returns the shape of this item as a QPainterPath in local coordinates. :rtype: QPainterPath """ path = QPainterPath() path.addPath(self.selection) path.addPolygon(self.head) if self.isSelected(): for shape in self.handles: path.addEllipse(shape) for shape in self.anchors.values(): path.addEllipse(shape) return path
def set_shape(self, width, height): ''' Define the symbol shape ''' circ = min(width, height) path = QPainterPath() path.addEllipse(0, 0, circ, circ) point1 = path.pointAtPercent(0.625) point2 = path.pointAtPercent(0.125) point3 = path.pointAtPercent(0.875) point4 = path.pointAtPercent(0.375) path.moveTo(point1) path.lineTo(point2) path.moveTo(point3) path.lineTo(point4) self.setPath(path) # call Join superclass, otherwise symbol will take Join shape super(Join, self).set_shape(circ, circ)
def set_shape(self, width, height): ''' Define the shape of the LABEL symbol ''' path = QPainterPath() path.addEllipse(0, height / 2, width / 4, height / 2) path.moveTo(width / 4, height * 3 / 4) path.lineTo(width / 2, height * 3 / 4) # Add arrow head path.moveTo(width / 2 - 5, height * 3 / 4 - 5) path.lineTo(width / 2, height * 3 / 4) path.lineTo(width / 2 - 5, height * 3 / 4 + 5) # Add vertical line in the middle of the symbol path.moveTo(width / 2, 0) path.lineTo(width / 2, height) # Make sure the bounding rect is withing specifications path.moveTo(width, height) self.setPath(path) super(Label, self).set_shape(width, height)
def draw_path(self): l, s, d = 45, 10, 10 proj = self.plan.projection.dot orig = np.array([0, 0]) axes = QPainterPath() axes.addPath(self.axis_arrow("x", orig, orig+l*proj([1, 0, 0]), s)) axes.addPath(self.axis_arrow("y", orig, orig+l*proj([0, 1, 0]), s)) axes.addPath(self.axis_arrow("z", orig, orig+l*proj([0, 0, 1]), s)) tran = self.deviceTransform(self.plan.viewportTransform()).inverted()[0] view = tran.mapRect(QRectF(self.plan.viewport().rect())) rect = axes.boundingRect() axes.translate(view.left() + view.width()/15 - rect.left(), view.bottom() - view.height()/15 - rect.bottom()) path = QPainterPath() path.addPath(axes) path.addEllipse(-d/2, -d/2, d, d) return path
class _MpcbAnimation(QPropertyAnimation): def __init__(self, parent, target, index, easing = QEasingCurve.InQuad): super(_MpcbAnimation, self).__init__(target, b"pos") self.parent = parent self.m_pathType = 1 self.easing = easing self.createAnimation(target, index) def createAnimation(self, target, index): '''创建动画''' self.m_path = QPainterPath() if self.easing != -1: self.setEasingCurve(self.easing) self.setStartValue(QPointF(0, 0)) self.setEndValue(QPointF(90, 90)) self.setDuration(2000) self.setLoopCount(-1) def updateCurrentTime(self, currentTime): if self.m_pathType: if self.m_path.isEmpty(): end = self.endValue() start = self.startValue() self.m_path.moveTo(start) self.m_path.addEllipse(QRectF(start, end)) dura = self.duration() if dura == 0: progress = 1.0 else: progress = (((currentTime - 1) % dura) + 1) / float(dura) easedProgress = self.easingCurve().valueForProgress(progress) if easedProgress > 1.0: easedProgress -= 1.0 elif easedProgress < 0: easedProgress += 1.0 pt = self.m_path.pointAtPercent(easedProgress) self.updateCurrentValue(pt) self.valueChanged.emit(pt) else: super(_MpcbAnimation, self).updateCurrentTime(currentTime)
def paintCorners(painter, corners, rect): # FIXME: This only works right for orthogonal maps right now hx = rect.width() / 2 hy = rect.height() / 2 x = corners if x==Corners.TopLeft: painter.drawPie(rect.translated(-hx, -hy), -90 * 16, 90 * 16) elif x==Corners.TopRight: painter.drawPie(rect.translated(hx, -hy), 180 * 16, 90 * 16) elif x==Corners.TopRight | Corners.TopLeft: painter.drawRect(rect.x(), rect.y(), rect.width(), hy) elif x==Corners.BottomLeft: painter.drawPie(rect.translated(-hx, hy), 0, 90 * 16) elif x==Corners.BottomLeft | Corners.TopLeft: painter.drawRect(rect.x(), rect.y(), hx, rect.height()) elif x==Corners.BottomLeft | Corners.TopRight: painter.drawPie(rect.translated(-hx, hy), 0, 90 * 16) painter.drawPie(rect.translated(hx, -hy), 180 * 16, 90 * 16) elif x==Corners.BottomLeft | Corners.TopRight | Corners.TopLeft: fill = QPainterPath() ellipse = QPainterPath() fill.addRect(rect) ellipse.addEllipse(rect.translated(hx, hy)) painter.drawPath(fill.subtracted(ellipse)) elif x==Corners.BottomRight: painter.drawPie(rect.translated(hx, hy), 90 * 16, 90 * 16) elif x==Corners.BottomRight | Corners.TopLeft: painter.drawPie(rect.translated(-hx, -hy), -90 * 16, 90 * 16) painter.drawPie(rect.translated(hx, hy), 90 * 16, 90 * 16) elif x==Corners.BottomRight | Corners.TopRight: painter.drawRect(rect.x() + hx, rect.y(), hx, rect.height()) elif x==Corners.BottomRight | Corners.TopRight | Corners.TopLeft: fill = QPainterPath() ellipse = QPainterPath() fill.addRect(rect) ellipse.addEllipse(rect.translated(-hx, hy)) painter.drawPath(fill.subtracted(ellipse)) elif x==Corners.BottomRight | Corners.BottomLeft: painter.drawRect(rect.x(), rect.y() + hy, rect.width(), hy) elif x==Corners.BottomRight | Corners.BottomLeft | Corners.TopLeft: fill = QPainterPath() ellipse = QPainterPath() fill.addRect(rect) ellipse.addEllipse(rect.translated(hx, -hy)) painter.drawPath(fill.subtracted(ellipse)) elif x==Corners.BottomRight | Corners.BottomLeft | Corners.TopRight: fill = QPainterPath() ellipse = QPainterPath() fill.addRect(rect) ellipse.addEllipse(rect.translated(-hx, -hy)) painter.drawPath(fill.subtracted(ellipse)) elif x==Corners.BottomRight | Corners.BottomLeft | Corners.TopRight | Corners.TopLeft: painter.drawRect(rect)
def shape(self, object): path = QPainterPath() if (not object.cell().isEmpty()): path.addRect(self.boundingRect(object)) else: x = object.shape() if x==MapObject.Rectangle: bounds = object.bounds() if (bounds.isNull()): path.addEllipse(bounds.topLeft(), 20, 20) else: path.addRoundedRect(bounds, 10, 10) elif x==MapObject.Polygon or x==MapObject.Polyline: pos = object.position() polygon = object.polygon().translated(pos) screenPolygon = self.pixelToScreenCoords_(polygon) if (object.shape() == MapObject.Polygon): path.addPolygon(screenPolygon) else: for i in range(1, screenPolygon.size()): path.addPolygon(self.lineToPolygon(screenPolygon[i - 1], screenPolygon[i])) path.setFillRule(Qt.WindingFill) elif x==MapObject.Ellipse: bounds = object.bounds() if (bounds.isNull()): path.addEllipse(bounds.topLeft(), 20, 20) else: path.addEllipse(bounds) return path
def paintEvent(self, event): self._alignmentPaths = [] painter = QPainter(self) painter.setPen(QColor(45, 45, 45)) circleRadius = self._circleRadius padding = self._padding rect = event.rect() size = min(rect.height(), rect.width()) offset = .5 * (rect.width() - size) painter.translate(offset, 0) borderRect = rect.__class__( rect.left() + circleRadius + padding, rect.top() + circleRadius + padding, size - 2 * (circleRadius + padding), size - 2 * (circleRadius + padding)) borderPath = QPainterPath() borderPath.addRect(*borderRect.getRect()) columnCount = 3 radioPath = QPainterPath() selectedPath = QPainterPath() for row in range(columnCount): for col in range(columnCount): index = row * columnCount + col path = QPainterPath() path.addEllipse( padding + col * .5 * borderRect.width(), padding + row * .5 * borderRect.height(), 2 * circleRadius, 2 * circleRadius) if self._alignment == index: selectedPath = path self._alignmentPaths.append(path.translated(offset, 0)) radioPath.addPath(path) painter.drawPath(borderPath - radioPath) painter.setRenderHint(QPainter.Antialiasing) painter.drawPath(radioPath) painter.fillPath(selectedPath, Qt.black)
class Animation(QPropertyAnimation): LinearPath, CirclePath = range(2) def __init__(self, target, prop): super(Animation, self).__init__(target, prop) self.setPathType(Animation.LinearPath) def setPathType(self, pathType): self.m_pathType = pathType self.m_path = QPainterPath() def updateCurrentTime(self, currentTime): if self.m_pathType == Animation.CirclePath: if self.m_path.isEmpty(): end = self.endValue() start = self.startValue() self.m_path.moveTo(start) self.m_path.addEllipse(QRectF(start, end)) dura = self.duration() if dura == 0: progress = 1.0 else: progress = (((currentTime - 1) % dura) + 1) / float(dura) easedProgress = self.easingCurve().valueForProgress(progress) if easedProgress > 1.0: easedProgress -= 1.0 elif easedProgress < 0: easedProgress += 1.0 pt = self.m_path.pointAtPercent(easedProgress) self.updateCurrentValue(pt) self.valueChanged.emit(pt) else: super(Animation, self).updateCurrentTime(currentTime)
def setupShapes(self): truck = QPainterPath() truck.setFillRule(Qt.WindingFill) truck.moveTo(0.0, 87.0) truck.lineTo(0.0, 60.0) truck.lineTo(10.0, 60.0) truck.lineTo(35.0, 35.0) truck.lineTo(100.0, 35.0) truck.lineTo(100.0, 87.0) truck.lineTo(0.0, 87.0) truck.moveTo(17.0, 60.0) truck.lineTo(55.0, 60.0) truck.lineTo(55.0, 40.0) truck.lineTo(37.0, 40.0) truck.lineTo(17.0, 60.0) truck.addEllipse(17.0, 75.0, 25.0, 25.0) truck.addEllipse(63.0, 75.0, 25.0, 25.0) clock = QPainterPath() clock.addEllipse(-50.0, -50.0, 100.0, 100.0) clock.addEllipse(-48.0, -48.0, 96.0, 96.0) clock.moveTo(0.0, 0.0) clock.lineTo(-2.0, -2.0) clock.lineTo(0.0, -42.0) clock.lineTo(2.0, -2.0) clock.lineTo(0.0, 0.0) clock.moveTo(0.0, 0.0) clock.lineTo(2.732, -0.732) clock.lineTo(24.495, 14.142) clock.lineTo(0.732, 2.732) clock.lineTo(0.0, 0.0) house = QPainterPath() house.moveTo(-45.0, -20.0) house.lineTo(0.0, -45.0) house.lineTo(45.0, -20.0) house.lineTo(45.0, 45.0) house.lineTo(-45.0, 45.0) house.lineTo(-45.0, -20.0) house.addRect(15.0, 5.0, 20.0, 35.0) house.addRect(-35.0, -15.0, 25.0, 25.0) text = QPainterPath() font = QFont() font.setPixelSize(50) fontBoundingRect = QFontMetrics(font).boundingRect("Qt") text.addText(-QPointF(fontBoundingRect.center()), font, "Qt") self.shapes = (clock, house, text, truck) self.shapeComboBox.activated.connect(self.shapeSelected)
def paintEvent(self, event): p = QPainter() p.begin(self) self._normalMap.render(p, event.rect()) p.setPen(Qt.black) p.drawText(self.rect(), Qt.AlignBottom | Qt.TextWordWrap, "Map data CCBYSA 2009 OpenStreetMap.org contributors") p.end() if self.zoomed: 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(255, 255, 255, 0)) g.setColorAt(0.5, QColor(128, 128, 128, 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: p = QPainter(self.zoomPixmap) p.translate(-xy) self._largeMap.render(p, QRect(xy, box)) p.end() clipPath = QPainterPath() clipPath.addEllipse(QPointF(center), ring, ring) p = QPainter(self) p.setRenderHint(QPainter.Antialiasing) p.setClipPath(clipPath) p.drawPixmap(corner, self.zoomPixmap) p.setClipping(False) p.drawPixmap(corner, self.maskPixmap) p.setPen(Qt.gray) p.drawPath(clipPath) if self.invert: p = QPainter(self) p.setCompositionMode(QPainter.CompositionMode_Difference) p.fillRect(event.rect(), Qt.white) p.end()
def _itemsAt(self, func, obj, justOne=True): """ Go through all anchors, points and components (in this order) in the glyph, construct their canvas path and list items for which *func(path, obj)* returns True, or only return the first item if *justOne* is set to True. An item is a (point, contour) or (anchor, None) or (component, None) tuple. The second argument permits accessing parent contour to post notifications. Here is a sample *func* function that tests whether item with path *path* contains *pos*: def myFunction(path, pos): return path.contains(pos) This is useful to find out whether an item was clicked on canvas. """ scale = self._inverseScale # TODO: export this from drawing or use QSettings. # anchor anchorSize = 6 * scale anchorHalfSize = anchorSize / 2 # offCurve offWidth = 5 * scale offHalf = offWidth / 2.0 # onCurve onWidth = 7 * scale onHalf = onWidth / 2.0 # onCurve smooth smoothWidth = 8 * scale smoothHalf = smoothWidth / 2.0 if not justOne: ret = dict( anchors=[], contours=[], points=[], components=[], ) for anchor in reversed(self._glyph.anchors): path = QPainterPath() path.addEllipse(anchor.x - anchorHalfSize, anchor.y - anchorHalfSize, anchorSize, anchorSize) if func(path, obj): if justOne: return (anchor, None) ret["anchors"].append(anchor) for contour in reversed(self._glyph): for point in contour: path = QPainterPath() if point.segmentType is None: x = point.x - offHalf y = point.y - offHalf path.addEllipse(x, y, offWidth, offWidth) elif point.smooth: x = point.x - smoothHalf y = point.y - smoothHalf path.addEllipse(x, y, smoothWidth, smoothWidth) else: x = point.x - onHalf y = point.y - onHalf path.addRect(x, y, onWidth, onWidth) if func(path, obj): if justOne: return (point, contour) ret["contours"].append(contour) ret["points"].append(point) for component in reversed(self._glyph.components): path = component.getRepresentation("defconQt.QPainterPath") if func(path, obj): if justOne: return (component, None) ret["components"].append(component) if not justOne: return ret return None
def drawGlyphPoints( painter, glyph, scale, rect, drawStartPoints=True, drawOnCurves=True, drawOffCurves=True, drawCoordinates=False, drawSelection=True, onCurveColor=None, otherColor=None, backgroundColor=None): if onCurveColor is None: layer = glyph.layer if layer is not None and layer.color is not None: onCurveColor = colorToQColor(layer.color) else: onCurveColor = defaultColor("glyphOnCurvePoints") if otherColor is None: otherColor = defaultColor("glyphOtherPoints") if backgroundColor is None: backgroundColor = defaultColor("background") # get the outline data outlineData = glyph.getRepresentation("defconQt.OutlineInformation") points = [] # start points if drawStartPoints and outlineData["startPoints"]: startWidth = startHeight = 15 * scale startHalf = startWidth / 2.0 path = QPainterPath() for point, angle in outlineData["startPoints"]: x, y = point if angle is not None: path.moveTo(x, y) path.arcTo(x - startHalf, y - startHalf, startWidth, startHeight, 180 - angle, 180) path.closeSubpath() else: path.addEllipse( x - startHalf, y - startHalf, startWidth, startHeight) startPointColor = QColor(otherColor) aF = startPointColor.alphaF() startPointColor.setAlphaF(aF * .3) painter.fillPath(path, startPointColor) # handles if drawOffCurves and outlineData["offCurvePoints"]: painter.save() painter.setPen(otherColor) for pt1, pt2 in outlineData["bezierHandles"]: x1, y1 = pt1 x2, y2 = pt2 # TODO: should lineWidth account scale by default drawLine(painter, x1, y1, x2, y2, 1.0 * scale) painter.restore() # on curve if drawOnCurves and outlineData["onCurvePoints"]: width = 7 * scale half = width / 2.0 smoothWidth = 8 * scale smoothHalf = smoothWidth / 2.0 painter.save() path = QPainterPath() selectedPath = QPainterPath() for point in outlineData["onCurvePoints"]: x, y = point["point"] points.append((x, y)) pointPath = QPainterPath() if point["smooth"]: x -= smoothHalf y -= smoothHalf pointPath.addEllipse(x, y, smoothWidth, smoothWidth) else: x -= half y -= half pointPath.addRect(x, y, width, width) if drawSelection and point["selected"]: selectedPath.addPath(pointPath) path.addPath(pointPath) pen = QPen(onCurveColor) pen.setWidthF(1.5 * scale) painter.setPen(pen) painter.fillPath(selectedPath, onCurveColor) painter.drawPath(path) painter.restore() # off curve if drawOffCurves and outlineData["offCurvePoints"]: # lines # points offWidth = 5 * scale offHalf = offWidth / 2.0 path = QPainterPath() selectedPath = QPainterPath() for point in outlineData["offCurvePoints"]: x, y = point["point"] points.append((x, y)) pointPath = QPainterPath() x -= offHalf y -= offHalf pointPath.addEllipse(x, y, offWidth, offWidth) if drawSelection and point["selected"]: selectedPath.addPath(pointPath) else: path.addPath(pointPath) pen = QPen(otherColor) pen.setWidthF(3.0 * scale) painter.save() painter.setPen(pen) painter.drawPath(path) painter.fillPath(path, QBrush(backgroundColor)) painter.drawPath(selectedPath) painter.fillPath(selectedPath, QBrush(otherColor)) painter.restore() # coordinates if drawCoordinates: otherColor = QColor(otherColor) otherColor.setAlphaF(otherColor.alphaF() * .6) painter.save() painter.setPen(otherColor) # TODO: decision + color font = painter.font() font.setPointSize(7) painter.setFont(font) for x, y in points: posX = x # TODO: We use + here because we align on top. Consider abstracting # yOffset. posY = y + 3 x = round(x, 1) if int(x) == x: x = int(x) y = round(y, 1) if int(y) == y: y = int(y) text = "%d %d" % (x, y) drawTextAtPoint(painter, text, posX, posY, scale, xAlign="center", yAlign="top") painter.restore()
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 fontSize = painter.font().pointSize() 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: 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 shape(self): path = QPainterPath() path.addEllipse(-10, -10, 20, 20) return path
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 ellipsePath(x, y, size): halfSize = size / 2 path = QPainterPath() path.addEllipse(x - halfSize, y - halfSize, size, size) return path
def _itemsAt(self, func, obj, justOne=True): """ Go through all anchors, points and components (in this order) in the glyph, construct their canvas path and list items for which *func(path, obj)* returns True, or only return the first item if *justOne* is set to True. An item is a (point, contour) or (anchor, None) or (component, None) tuple. The second argument permits accessing parent contour to post notifications. Here is a sample *func* function that tests whether item with path *path* contains *pos*: def myFunction(path, pos): return path.contains(pos) This is useful to find out whether an item was clicked on canvas. """ scale = self._inverseScale # TODO: export this from drawing or use QSettings. # anchor anchorSize = 6 * scale anchorHalfSize = anchorSize / 2 # offCurve offWidth = 5 * scale offHalf = offWidth / 2 offStrokeWidth = 3 * scale # onCurve onWidth = 7 * scale onHalf = onWidth / 2 onStrokeWidth = 1.5 * scale # onCurve smooth smoothWidth = 8 * scale smoothHalf = smoothWidth / 2 # guideline pt guidelineStrokeWidth = 1 * scale if not justOne: ret = dict( anchors=[], contours=[], points=[], components=[], guidelines=[], image=None, ) # anchors for anchor in reversed(self._glyph.anchors): path = QPainterPath() path.addEllipse(anchor.x - anchorHalfSize, anchor.y - anchorHalfSize, anchorSize, anchorSize) if func(path, obj): if justOne: return (anchor, None) ret["anchors"].append(anchor) # points for contour in reversed(self._glyph): for point in contour: path = QPainterPath() if point.segmentType is None: x = point.x - offHalf y = point.y - offHalf path.addEllipse(x, y, offWidth, offWidth) strokeWidth = offStrokeWidth else: if point.smooth: x = point.x - smoothHalf y = point.y - smoothHalf path.addEllipse(x, y, smoothWidth, smoothWidth) else: x = point.x - onHalf y = point.y - onHalf path.addRect(x, y, onWidth, onWidth) strokeWidth = onStrokeWidth path = _shapeFromPath(path, strokeWidth) if func(path, obj): if justOne: return (point, contour) ret["contours"].append(contour) ret["points"].append(point) # components for component in reversed(self._glyph.components): path = component.getRepresentation("TruFont.QPainterPath") if func(path, obj): if justOne: return (component, None) ret["components"].append(component) # guideline for guideline in UIGlyphGuidelines(self._glyph): if None not in (guideline.x, guideline.y): # point x = guideline.x - smoothHalf y = guideline.y - smoothHalf path = QPainterPath() path.addEllipse(x, y, smoothWidth, smoothWidth) path = _shapeFromPath(path, guidelineStrokeWidth) if func(path, obj): if justOne: return (guideline, None) ret["guidelines"].append(guideline) # TODO: catch line if selected # image image = self._glyph.image pixmap = image.getRepresentation("defconQt.QPixmap") if pixmap is not None: path = QPainterPath() transform = QTransform(*image.transformation) rect = transform.mapRect(QRectF(pixmap.rect())) path.addRect(*rect.getCoords()) if func(path, obj): if justOne: return (image, None) ret["image"] = image if not justOne: return ret return None