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 orbit(self): """Return a QPainterPath that shows the beam orbit.""" a, b = self.endpoints() path = QPainterPath() path.moveTo(*a) path.lineTo(*b) return path
class ModCrossButton(QPushButton): def __init__(self,parent,path=None): QPushButton.__init__(self,parent) self.parent=parent #self.setAttribute(Qt.WA_TranslucentBackground, True) self.backgroundColor = QPalette().light().color() self.backgroundColor.setRgb(157,157,157) #(220,203,231) #self.backgroundColor.setAlpha(100) self.brush=QBrush(Qt.SolidPattern) def paintEvent(self,event): self.wide=self.width() self.high=self.height() self.xdis=self.wide/7 self.ydis=self.xdis self.path=QPainterPath() self.path.setFillRule(Qt.OddEvenFill) self.path.moveTo(self.wide/2, self.high/2-self.xdis) self.path.arcTo(0,0, self.wide, self.high,0,360) #self.path.closeSubpath() self.path.moveTo(self.wide/2-self.xdis/2, self.ydis) self.path.lineTo(self.wide/2-self.xdis/2, self.high/2-self.xdis/2) self.path.lineTo(self.ydis, self.high/2-self.xdis/2) self.path.lineTo(self.ydis, self.high/2+self.xdis/2) self.path.lineTo(self.wide/2-self.xdis/2, self.high/2+self.xdis/2) self.path.lineTo(self.wide/2-self.xdis/2, self.high-self.ydis) self.path.lineTo(self.wide/2+self.xdis/2, self.high-self.ydis) self.path.lineTo(self.wide/2+self.xdis/2, self.high/2+self.xdis/2) self.path.lineTo(self.wide-self.ydis, self.high/2+self.xdis/2) self.path.lineTo(self.wide-self.ydis, self.high/2-self.xdis/2) self.path.lineTo(self.wide/2+self.xdis/2, self.high/2-self.xdis/2) self.path.lineTo(self.wide/2+self.xdis/2, self.ydis) self.path.closeSubpath() self.brush.setColor(self.backgroundColor) self.painter=QPainter(self) self.painter.setRenderHint(QPainter.Antialiasing) self.painter.setPen(Qt.NoPen) self.painter.setBrush(self.brush) self.painter.drawPath(self.path) self.painter.end() #def mousePressEvent(self,ev): # self.parent.close() def enterEvent(self,ev): self.backgroundColor.setRgb(242,146,52) self.update() def leaveEvent(self,ev): self.backgroundColor.setRgb(157,157,157) self.update()
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 createRotateArrow(): arrowHeadPos = 12 arrowHeadLength = 4.5 arrowHeadWidth = 5 bodyWidth = 1.5 outerArcSize = arrowHeadPos + bodyWidth - arrowHeadLength innerArcSize = arrowHeadPos - bodyWidth - arrowHeadLength path = QPainterPath() path.moveTo(arrowHeadPos, 0) path.lineTo(arrowHeadPos + arrowHeadWidth, arrowHeadLength) path.lineTo(arrowHeadPos + bodyWidth, arrowHeadLength) path.arcTo(QRectF(arrowHeadLength - outerArcSize, arrowHeadLength - outerArcSize, outerArcSize * 2, outerArcSize * 2), 0, -90) path.lineTo(arrowHeadLength, arrowHeadPos + arrowHeadWidth) path.lineTo(0, arrowHeadPos) path.lineTo(arrowHeadLength, arrowHeadPos - arrowHeadWidth) path.lineTo(arrowHeadLength, arrowHeadPos - bodyWidth) path.arcTo(QRectF(arrowHeadLength - innerArcSize, arrowHeadLength - innerArcSize, innerArcSize * 2, innerArcSize * 2), -90, 90) path.lineTo(arrowHeadPos - arrowHeadWidth, arrowHeadLength) path.closeSubpath() return path
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 paintEvent(self, event): rect = QRect(10, 20, 80, 60) path = QPainterPath() path.moveTo(20, 80) path.lineTo(20, 30) path.cubicTo(80, 0, 50, 50, 80, 80) startAngle = 30 * 16 arcLength = 120 * 16 painter = QPainter(self) painter.setPen(self.pen) painter.setBrush(self.brush) if self.antialiased: painter.setRenderHint(QPainter.Antialiasing) for x in range(0, self.width(), 100): for y in range(0, self.height(), 100): painter.save() painter.translate(x, y) if self.transformed: painter.translate(50, 50) painter.rotate(60.0) painter.scale(0.6, 0.9) painter.translate(-50, -50) if self.shape == RenderArea.Line: painter.drawLine(rect.bottomLeft(), rect.topRight()) elif self.shape == RenderArea.Points: painter.drawPoints(RenderArea.points) elif self.shape == RenderArea.Polyline: painter.drawPolyline(RenderArea.points) elif self.shape == RenderArea.Polygon: painter.drawPolygon(RenderArea.points) elif self.shape == RenderArea.Rect: painter.drawRect(rect) elif self.shape == RenderArea.RoundedRect: painter.drawRoundedRect(rect, 25, 25, Qt.RelativeSize) elif self.shape == RenderArea.Ellipse: painter.drawEllipse(rect) elif self.shape == RenderArea.Arc: painter.drawArc(rect, startAngle, arcLength) elif self.shape == RenderArea.Chord: painter.drawChord(rect, startAngle, arcLength) elif self.shape == RenderArea.Pie: painter.drawPie(rect, startAngle, arcLength) elif self.shape == RenderArea.Path: painter.drawPath(path) elif self.shape == RenderArea.Text: painter.drawText(rect, Qt.AlignCenter, "PyQt by\nRiverbank Computing") elif self.shape == RenderArea.Pixmap: painter.drawPixmap(10, 10, self.pixmap) painter.restore() painter.setPen(self.palette().dark().color()) painter.setBrush(Qt.NoBrush) painter.drawRect(QRect(0, 0, self.width() - 1, self.height() - 1))
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 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 _insertGen( path: QPainterPath, start: QPointF, c1: QPointF, p1: QPointF, c2: QPointF): path.moveTo(start) path.quadTo(c1, p1) path.quadTo(c2, start)
def _addLinesToPainterPath( path: QPainterPath, p1: QPointF, p2: QPointF, p3: QPointF, p4: QPointF): path.moveTo(p1) path.lineTo(p2) path.moveTo(p3) path.lineTo(p4)
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 set_shape(self, width, height): ''' Compute the polygon to fit in width, height ''' path = QPainterPath() path.addRoundedRect(0, 0, width, height, height / 2, height / 2) path.moveTo(min(width / 2, height / 2), 0) path.lineTo(min(width / 2, height / 2), height) path.moveTo(max(width / 2, width - height / 2), 0) path.lineTo(max(width / 2, width - height / 2), height) self.setPath(path) super(Start, 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 set_shape(self, width, height): ''' Compute the polygon to fit in width, height ''' path = QPainterPath() path.addRect(0, 0, width, height) path.moveTo(7, 0) path.lineTo(7, height) path.moveTo(width - 7, 0) path.lineTo(width - 7, height) self.setPath(path) super(ProcedureCall, self).set_shape(width, height)
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 doSquare(self, part_item: GridNucleicAcidPartItemT, radius: float, bounds: RectT): """ Args: part_item: Description radius: Description bounds: Description """ doLattice = SquareDnaPart.latticeCoordToModelXY doPosition = SquareDnaPart.positionToLatticeCoordRound 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, scale_factor=sf) row_h, col_h = doPosition(radius, x_h, -y_h, 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 + 1): 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 # pen up # DO VERTICAL LINES if draw_lines: for j in range(col_l, col_h + 1): for i in range(row_l, row_h + 1): x, y = doLattice(radius, i, j, scale_factor=sf) if is_pen_down: path.lineTo(x, -y) else: is_pen_down = True path.moveTo(x, -y) is_pen_down = False # pen up self.setPath(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)
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 _getLeftBottomCornerPath(self): height = self.height() borderRadius = self.borderRadius shadowMargin = self.shadowMargin shadowRadius = self.shadowRadius path = QPainterPath() path.moveTo(0, height - shadowRadius) path.arcTo(0, height - 2 * shadowRadius, 2 * shadowRadius, 2 * shadowRadius, 180, 90) path.lineTo(shadowRadius, height - shadowMargin) path.arcTo(shadowMargin, height - shadowRadius - borderRadius, 2 * borderRadius, 2 * borderRadius, 270, -90) path.lineTo(0, height - shadowRadius) return path
def set_shape(self, width, height): ''' Define the polygon of the text symbol ''' path = QPainterPath() path.moveTo(width - 10, 0) path.lineTo(0, 0) path.lineTo(0, height) path.lineTo(width, height) path.lineTo(width, 10) path.lineTo(width - 10, 10) path.lineTo(width - 10, 0) path.lineTo(width, 10) self.setPath(path) super(TextSymbol, self).set_shape(width, height)
def _getRightTopCornerPath(self): width = self.width() borderRadius = self.borderRadius shadowMargin = self.shadowMargin shadowRadius = self.shadowRadius path = QPainterPath() path.moveTo(width - shadowRadius, 0) path.arcTo(width - 2 * shadowRadius, 0, 2 * shadowRadius, 2 * shadowRadius, 90, -90) path.lineTo(width - shadowMargin, shadowRadius) path.arcTo(width - shadowRadius - borderRadius, shadowMargin, 2 * borderRadius, 2 * borderRadius, 0, 90) path.lineTo(width - shadowRadius, 0) return path
def painterPath(self): i_g = self._item_group # the childrenBoundingRect is necessary to get this to work rect = self.mapRectFromItem(i_g, i_g.childrenBoundingRect()) radius = self._RADIUS path = QPainterPath() path.addRoundedRect(rect, radius, radius) path.moveTo(rect.right(),\ rect.center().y()) path.lineTo(rect.right() + radius / 2,\ rect.center().y()) return path
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 paint(self, painter, styleOption, widget): ''' Reimplemented to paint elements in alternating colors ''' path = self.path() # alias pathEnd = None i = 0 while True: try: element = path.elementAt(i) #print type(element), element.type if element.isMoveTo(): pathEnd = QPointF(element.x, element.y) i+=1 elif element.isCurveTo(): # Gather curve data, since is spread across elements of type curveElementData cp1 = QPointF(element.x, element.y) element = path.elementAt(i+1) cp2 = QPointF(element.x, element.y) element = path.elementAt(i+2) newEnd = QPointF(element.x, element.y) # create a subpath, since painter has no drawCubic method subpath=QPainterPath() subpath.moveTo(pathEnd) subpath.cubicTo(cp1, cp2, newEnd) painter.drawPath(subpath) pathEnd = newEnd i+=3 else: print "unhandled path element", element.type i+=1 """ TODO: if SegmentStringss contain lines (w/o Direction ControlPoints) !!! We don't use QPathElements of type Line elif element.isLineTo(): newEnd = QPointF(element.x, element.y) painter.drawLine(pathEnd, newEnd) pathEnd = newEnd i+=1 """ if i >= path.elementCount(): break except Exception as inst: print inst break # Alternate colors if i%2 == 1: painter.setPen(Qt.green) else: painter.setPen(Qt.red)
def set_shape(self, width, height): ''' ANSWER has round, disjoint sides - does not fit in a polygon ''' self.width, self.height = width, height point = 20 #width / 2.85 path = QPainterPath() left = QRect(0, 0, point, height) right = QRect(width - point, 0, point, height) path.arcMoveTo(left, 125) path.arcTo(left, 125, 110) path.arcMoveTo(right, -55) path.arcTo(right, -55, 110) path.moveTo(width, height) self.setPath(path) super(DecisionAnswer, self).set_shape(width, height)
def _getRightBottomCornerPath(self): width = self.width() height = self.height() borderRadius = self.borderRadius shadowMargin = self.shadowMargin shadowRadius = self.shadowRadius path = QPainterPath() path.moveTo(width - shadowRadius, height) path.arcTo(width - 2 * shadowRadius, height - 2 * shadowRadius, 2 * shadowRadius, 2 * shadowRadius, 270, 90) path.lineTo(width - shadowMargin, height - shadowRadius) path.arcTo(width - shadowRadius - borderRadius, height - shadowRadius - borderRadius, 2 * borderRadius, 2 * borderRadius, 0, -90) path.lineTo(width - shadowRadius, height) return path
def set_shape(self, width, height): ''' Compute the polygon to fit in width, height ''' path = QPainterPath() path.moveTo(7, 0) path.lineTo(0, 7) path.lineTo(0, height - 7) path.lineTo(7, height) path.lineTo(width - 7, height) path.lineTo(width, height - 7) path.lineTo(width, 7) path.lineTo(width - 7, 0) path.lineTo(7, 0) self.setPath(path) super(Process, self).set_shape(width, height)
def outline(self): """Return a QPainterPath that outlines the element.""" r1, r2 = self.walls p0, p1 = self.endpoints() proj2D = self.plan.projection.dot vec0 = normalize(np.dot(rot90, proj2D(list(self.rotate[0](0, 0, 1))))) vec1 = normalize(np.dot(rot90, proj2D(list(self.rotate[1](0, 0, 1))))) path = QPainterPath() path.moveTo(*(p0 - r2*vec0)) path.lineTo(*(p1 - r2*vec1)) path.lineTo(*(p1 + r1*vec1)) path.lineTo(*(p0 + r1*vec0)) path.closeSubpath() return path
class PointerTrackGhost(QGraphicsPathItem): ''' A ghost for freehand drawing. Graphic between current PointerPosition and last PointerTrack path segment generated, which lags. Finally replaced by a path segment. Hidden when user not using freehand tool. Implementation: extend QGraphicsPathItem. Use a path of lines, one for each pointerTrack value. That is, there is no attempt here to make it minimal or smooth; that is what the rest of freehand is doing. I.E. this has about the same density as a bitmap of the pointerTrack. This presents a simplified API to FreehandTool, to reduce coupling between FreehandTool and Qt. ''' def __init__(self, **kwargs): super(PointerTrackGhost, self).__init__(**kwargs) self.start = None # cached start/end (don't get it from self.path) self.end = None self.path = QPainterPath( ) # working copy, frequently setPath() to self. self.hide() assert self.isVisible() == False, 'initial PointerTrackGhost is hidden' def showAt(self, initialPosition): ''' Resume using self, at given position, with length zero. ''' #print "showAt", initialPosition assert self.isVisible() == False, 'resumed PointerTrackGhost is hidden' self.start = initialPosition self.end = initialPosition self._replacePath() self.show() # assert path length is zero assert self.isVisible() == True def updateStart(self, pointSCS): ''' Shorten self by changing start, towards end. Called when freehand generator has traced an increment: determined one or more segments (lines and splines) that fit a prefix of self's path. Said segments are now displayed, thus remove the prefix of self's path that they represent. This implementation replaces working path with a single lineTo. (See below for work in progress, alternate implementation where we truncate a prefix of existing path.) Assert new start point is near self.end (so that result path is shorter.) ''' # not assert is visible, but might be assert isinstance(pointSCS, FreehandPoint) self.start = pointSCS self._replacePath() def _replacePath(self): ''' Completely abandon the working path and replace it with a new path, from cached start/end ''' self.path = QPainterPath() self.path.moveTo( self.start) # OLD self.floatSceneFromIntViewPoint(pointVCS)) self.path.lineTo(self.end) self.setPath(self.path) def updateEnd(self, point): ''' Update current path by appending lineTo new end point. ''' #print "updateEnd" assert isinstance(point, FreehandPoint) self.end = point self.path.lineTo(point) self.setPath(self.path) # hide() is inherited def floatSceneFromIntViewPoint(self, pointVCS): # !!! start point from FreehandTool is in View CS. pointViewInt = QPoint(pointVCS.x(), pointVCS.y()) pointSceneFloat = self.scene().views()[0].mapToScene(pointViewInt) return pointSceneFloat """
class PolygonWidget(QWidget): """PolygonWidget(QWidget) Provides a custom widget to display a polygon with properties and slots that can be used to customize its appearance. """ def __init__(self, parent=None): super(PolygonWidget, self).__init__(parent) self._sides = 5 self._innerRadius = 20 self._outerRadius = 50 self._angle = 0 self.createPath() self._innerColor = QColor(255, 255, 128) self._outerColor = QColor(255, 0, 128) self.createGradient() def paintEvent(self, event): painter = QPainter() painter.begin(self) painter.setRenderHint(QPainter.Antialiasing) painter.setBrush(QBrush(QColor(192, 192, 255))) painter.drawRect(event.rect()) painter.translate(self.width() / 2.0, self.height() / 2.0) painter.rotate(self._angle) painter.setBrush(QBrush(self.gradient)) painter.drawPath(self.path) painter.end() def sizeHint(self): return QSize(2 * self._outerRadius + 20, 2 * self._outerRadius + 20) def createPath(self): self.path = QPainterPath() angle = 2 * math.pi / self._sides self.path.moveTo(self._outerRadius, 0) for step in range(1, self._sides + 1): self.path.lineTo( self._innerRadius * math.cos((step - 0.5) * angle), self._innerRadius * math.sin((step - 0.5) * angle)) self.path.lineTo(self._outerRadius * math.cos(step * angle), self._outerRadius * math.sin(step * angle)) self.path.closeSubpath() def createGradient(self): center = QPointF(0, 0) self.gradient = QRadialGradient(center, self._outerRadius, center) self.gradient.setColorAt(0.5, QColor(self._innerColor)) self.gradient.setColorAt(1.0, QColor(self._outerColor)) # The angle property is implemented using the getAngle() and setAngle() # methods. def getAngle(self): return self._angle # The setAngle() setter method is also a slot. @pyqtSlot(int) def setAngle(self, angle): self._angle = min(max(0, angle), 360) self.update() angle = pyqtProperty(int, getAngle, setAngle) # The innerRadius property is implemented using the getInnerRadius() and # setInnerRadius() methods. def getInnerRadius(self): return self._innerRadius # The setInnerRadius() setter method is also a slot. @pyqtSlot(int) def setInnerRadius(self, radius): self._innerRadius = radius self.createPath() self.createGradient() self.update() innerRadius = pyqtProperty(int, getInnerRadius, setInnerRadius) # The outerRadius property is implemented using the getOuterRadius() and # setOuterRadius() methods. def getOuterRadius(self): return self._outerRadius # The setOuterRadius() setter method is also a slot. @pyqtSlot(int) def setOuterRadius(self, radius): self._outerRadius = radius self.createPath() self.createGradient() self.update() outerRadius = pyqtProperty(int, getOuterRadius, setOuterRadius) # The numberOfSides property is implemented using the getNumberOfSides() # and setNumberOfSides() methods. def getNumberOfSides(self): return self._sides # The setNumberOfSides() setter method is also a slot. @pyqtSlot(int) def setNumberOfSides(self, sides): self._sides = max(3, sides) self.createPath() self.update() numberOfSides = pyqtProperty(int, getNumberOfSides, setNumberOfSides) # The innerColor property is implemented using the getInnerColor() and # setInnerColor() methods. def getInnerColor(self): return self._innerColor def setInnerColor(self, color): self._innerColor = color self.createGradient() self.update() innerColor = pyqtProperty(QColor, getInnerColor, setInnerColor) # The outerColor property is implemented using the getOuterColor() and # setOuterColor() methods. def getOuterColor(self): return self._outerColor def setOuterColor(self, color): self._outerColor = color self.createGradient() self.update() outerColor = pyqtProperty(QColor, getOuterColor, setOuterColor)
def handleShapeDescription(self, shape, list, textOnly=False): if (shape.type() != "KoSvgTextShapeID" and textOnly is True): return shapeDesc = {} shapeDesc["name"] = shape.name() rect = shape.boundingBox() listOfPoints = [ rect.topLeft(), rect.topRight(), rect.bottomRight(), rect.bottomLeft() ] shapeDoc = minidom.parseString(shape.toSvg()) docElem = shapeDoc.documentElement svgRegExp = re.compile('[MLCSQHVATmlzcqshva]\d+\.?\d* \d+\.?\d*') transform = docElem.getAttribute("transform") coord = [] adjust = QTransform() # TODO: If we get global transform api, use that instead of parsing manually. if "translate" in transform: transform = transform.replace('translate(', '') for c in transform[:-1].split(" "): coord.append(float(c)) if len(coord) < 2: coord.append(coord[0]) adjust = QTransform(1, 0, 0, 1, coord[0], coord[1]) if "matrix" in transform: transform = transform.replace('matrix(', '') for c in transform[:-1].split(" "): coord.append(float(c)) adjust = QTransform(coord[0], coord[1], coord[2], coord[3], coord[4], coord[5]) path = QPainterPath() if docElem.localName == "path": dVal = docElem.getAttribute("d") listOfSvgStrings = [" "] listOfSvgStrings = svgRegExp.findall(dVal) if listOfSvgStrings: listOfPoints = [] for l in listOfSvgStrings: line = l[1:] coordinates = line.split(" ") if len(coordinates) < 2: coordinates.append(coordinates[0]) x = float(coordinates[-2]) y = float(coordinates[-1]) offset = QPointF() if l.islower(): offset = listOfPoints[0] if l.lower().startswith("m"): path.moveTo(QPointF(x, y) + offset) elif l.lower().startswith("h"): y = listOfPoints[-1].y() path.lineTo(QPointF(x, y) + offset) elif l.lower().startswith("v"): x = listOfPoints[-1].x() path.lineTo(QPointF(x, y) + offset) elif l.lower().startswith("c"): path.cubicTo(coordinates[0], coordinates[1], coordinates[2], coordinates[3], x, y) else: path.lineTo(QPointF(x, y) + offset) path.setFillRule(Qt.WindingFill) for polygon in path.simplified().toSubpathPolygons(adjust): for point in polygon: listOfPoints.append(point) elif docElem.localName == "rect": listOfPoints = [] if (docElem.hasAttribute("x")): x = float(docElem.getAttribute("x")) else: x = 0 if (docElem.hasAttribute("y")): y = float(docElem.getAttribute("y")) else: y = 0 w = float(docElem.getAttribute("width")) h = float(docElem.getAttribute("height")) path.addRect(QRectF(x, y, w, h)) for point in path.toFillPolygon(adjust): listOfPoints.append(point) elif docElem.localName == "ellipse": listOfPoints = [] if (docElem.hasAttribute("cx")): x = float(docElem.getAttribute("cx")) else: x = 0 if (docElem.hasAttribute("cy")): y = float(docElem.getAttribute("cy")) else: y = 0 ry = float(docElem.getAttribute("ry")) rx = float(docElem.getAttribute("rx")) path.addEllipse(QPointF(x, y), rx, ry) for point in path.toFillPolygon(adjust): listOfPoints.append(point) elif docElem.localName == "text": # NOTE: This only works for horizontal preformated text. Vertical text needs a different # ordering of the rects, and wraparound should try to take the shape it is wraped in. family = "sans-serif" if docElem.hasAttribute("font-family"): family = docElem.getAttribute("font-family") size = "11" if docElem.hasAttribute("font-size"): size = docElem.getAttribute("font-size") multilineText = True for el in docElem.childNodes: if el.nodeType == minidom.Node.TEXT_NODE: multilineText = False if multilineText: listOfPoints = [] listOfRects = [] # First we collect all the possible line-rects. for el in docElem.childNodes: if docElem.hasAttribute("font-family"): family = docElem.getAttribute("font-family") if docElem.hasAttribute("font-size"): size = docElem.getAttribute("font-size") fontsize = int(size) font = QFont(family, fontsize) string = el.toxml() string = re.sub("\<.*?\>", " ", string) string = string.replace(" ", " ") width = min( QFontMetrics(font).width(string.strip()), rect.width()) height = QFontMetrics(font).height() anchor = "start" if docElem.hasAttribute("text-anchor"): anchor = docElem.getAttribute("text-anchor") top = rect.top() if len(listOfRects) > 0: top = listOfRects[-1].bottom() if anchor == "start": spanRect = QRectF(rect.left(), top, width, height) listOfRects.append(spanRect) elif anchor == "end": spanRect = QRectF(rect.right() - width, top, width, height) listOfRects.append(spanRect) else: # Middle spanRect = QRectF(rect.center().x() - (width * 0.5), top, width, height) listOfRects.append(spanRect) # Now we have all the rects, we can check each and draw a # polygon around them. heightAdjust = ( rect.height() - (listOfRects[-1].bottom() - rect.top())) / len(listOfRects) for i in range(len(listOfRects)): span = listOfRects[i] addtionalHeight = i * heightAdjust if i == 0: listOfPoints.append(span.topLeft()) listOfPoints.append(span.topRight()) else: if listOfRects[i - 1].width() < span.width(): listOfPoints.append( QPointF(span.right(), span.top() + addtionalHeight)) listOfPoints.insert( 0, QPointF(span.left(), span.top() + addtionalHeight)) else: bottom = listOfRects[i - 1].bottom( ) + addtionalHeight - heightAdjust listOfPoints.append( QPointF(listOfRects[i - 1].right(), bottom)) listOfPoints.insert( 0, QPointF(listOfRects[i - 1].left(), bottom)) listOfPoints.append(QPointF(span.right(), rect.bottom())) listOfPoints.insert(0, QPointF(span.left(), rect.bottom())) path = QPainterPath() path.moveTo(listOfPoints[0]) for p in range(1, len(listOfPoints)): path.lineTo(listOfPoints[p]) path.closeSubpath() listOfPoints = [] for point in path.toFillPolygon(adjust): listOfPoints.append(point) shapeDesc["boundingBox"] = listOfPoints if (shape.type() == "KoSvgTextShapeID" and textOnly is True): shapeDesc["text"] = shape.toSvg() list.append(shapeDesc)
def updateMapping(self): if self.toolBox.currentIndex() == 2: # widget visible if self.mappingView.scene() is None: self.resetMappingScene() mappingscene = self.mappingView.scene() keypoints = [ item.scenePos() for item in mappingscene.items() if isinstance(item, QGraphicsEllipseItem) ] keypoints.sort(key=lambda p: p.x()) method = self.comboGrayscale.currentText() if method == self.cached_method and keypoints == self.cached_keypoints: return self.cached_keypoints = keypoints self.cached_method = method # update grayscaleMapping try: if method == 'Linear': keypoints = [[p.x(), 256 - p.y()] for p in keypoints] keypoints.insert(0, [0, 0]) keypoints.append([255, 255]) self.grayscaleMapping = np.interp( np.arange(256), [p[0] for p in keypoints], [p[1] for p in keypoints]) else: self.grayscaleMapping = np.arange(256) # log, exp, gamma need exactly one point if len(keypoints) != 1: pass else: p = keypoints[0] x0 = p.x() y0 = 256 - p.y() if method == 'Logarithmic': pass elif method == 'Exponential': pass elif method == 'Gamma': gamma = np.log(y0 / 256) / np.log(x0 / 256) self.grayscaleMapping = 256 * ( self.grayscaleMapping / 256)**gamma except Exception: self.grayscaleMapping = np.arange(256) path = QPainterPath() for i in range(0, 256): if i == 0: path.moveTo(0, 255 - self.grayscaleMapping[0]) else: path.lineTo(i, 255 - self.grayscaleMapping[i]) if self.mappingPathItem is not None: mappingscene.removeItem(self.mappingPathItem) self.mappingPathItem = mappingscene.addPath(path) self.grayscaleTransforming = grayscaleTransformation( self.img, self.grayscaleMapping) self.paint(self.grayscaleTransforming)
class FWHist(): def __init__(self, view, **kwargs): self.view = view self.scene = view.scene() #self.rect = self.scene.sceneRect() color = kwargs.get('color', QColor(Qt.black)) # color for default pen (histogram sline) self.pen_def = QPen(color, 0, Qt.SolidLine) self.hbins = kwargs.get('hbins', None) # histogram container HBins self.orient = kwargs.get('orient','H') # histogram orientation H or V self.pen = kwargs.get('pen', self.pen_def) # histogram line pen self.brush = kwargs.get('brush', QBrush()) # histogram filling brush self.zvalue = kwargs.get('zvalue',10) # z value for heirarchial visibility self.pen.setCosmetic(self.pen == self.pen_def) self.path = None self.path_item = None self.lst_of_items = [] if self.hbins is None: self.add_test() else: self.add_hist() def remove(self): for item in self.lst_of_items: self.scene.removeItem(item) self.lst_of_items=[] #self.scene.removeItem(self.path_item) #self.scene.destroyItemGroup(self.item_group) def update(self, hbins): self.remove() self.hbins = hbins self.add_hist() def __del__(self): self.remove() def add_hist(self): if self.path_item is not None: self.scene.removeItem(self.path_item) edges = self.hbins.binedges() # n+1 values = self.hbins.bin_data() #dtype=np.float64) self.path = QPainterPath() #QPointF(edges[0], 0)) #self.path.closeSubpath() if self.orient == 'V': self.path.moveTo(QPointF(0, edges[0])) for el, er, v in zip(edges[:-1], edges[1:], values): self.path.lineTo(QPointF(v, el)) self.path.lineTo(QPointF(v, er)) self.path.lineTo(QPointF(0, edges[-1])) else: self.path.moveTo(QPointF(edges[0], 0)) for el, er, v in zip(edges[:-1], edges[1:], values): self.path.lineTo(QPointF(el,v)) self.path.lineTo(QPointF(er,v)) self.path.lineTo(QPointF(edges[-1], 0.)) # add path with hist lines to scene self.lst_of_items=[] self.path_item = self.scene.addPath(self.path, self.pen, self.brush) self.path_item.setZValue(self.zvalue) self.lst_of_items.append(self.path_item)
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 line(self, x1, y1, x2, y2): path = QPainterPath() path.moveTo(x1, y1) path.lineTo(x2, y2) self.renderPath(path)
def point(self, x, y): path = QPainterPath() path.moveTo(x, y) path.lineTo(x + 0.1, y) self.renderPath(path)
def paintGraph(self, graph, painter): brush = QBrush(Qt.SolidPattern) pen = QPen() brush.setColor(Qt.white) if (self.show_subgraphs): for node in graph.nodes: if type(node) == Graph: subgraph = node self.paintSubgraph(subgraph, painter, pen, brush) for i, edge in enumerate(graph.edges): if ("color" in edge.kwargs.keys()): pen.setColor(QColor(edge.kwargs["color"])) else: pen.setColor(QColor("black")) if ("width" in edge.kwargs.keys()): pen.setWidth(int(edge.kwargs["width"])) else: pen.setWidth(1) painter.setPen(pen) painter.setBrush(brush) if (edge.source.parent_graph != graph and not self.show_subgraphs): gspos = edge.source.parent_graph.global_pos else: gspos = edge.source.global_pos if (edge.dest.parent_graph != graph and not self.show_subgraphs): gspos = edge.dest.parent_graph.global_pos else: gdpos = edge.dest.global_pos nb_next = 0 for j in range(i, len(graph.edges)): if (graph.edges[j].source == edge.source and graph.edges[j].dest == edge.dest): nb_next += 1 offset = [0, 0] if (nb_next % 2 == 1): offset[0] = 20 * (nb_next / 2) else: offset[0] = -20 * (nb_next / 2) path = QPainterPath() path.moveTo(gspos[0], gspos[1]) path.cubicTo(gspos[0], gspos[1], offset[0] + (gspos[0] + gdpos[0]) / 2, (gspos[1] + gdpos[1]) / 2, gdpos[0], gdpos[1]) painter.strokePath(path, pen) """ painter.drawLine(gspos[0],gspos[1], gdpos[0], gdpos[1]) """ # TODO : add more painting parameters for node in graph.nodes: if type(node) != Graph: if ("color" in node.kwargs.keys()): pen.setColor(QColor(node.kwargs["color"])) else: pen.setColor(QColor("black")) if ("fillcolor" in node.kwargs.keys()): if (":" in node.kwargs["fillcolor"]): gradient = QLinearGradient( node.pos[0] - node.size[0] / 2, node.pos[1], node.pos[0] + node.size[0] / 2, node.pos[1]) c = node.kwargs["fillcolor"].split(":") for i, col in enumerate(c): stop = i / (len(c) - 1) gradient.setColorAt(stop, QColor(col)) brush = QBrush(gradient) else: brush = QBrush(QColor(node.kwargs["fillcolor"])) else: brush = QBrush(QColor("white")) if ("width" in node.kwargs.keys()): pen.setWidth(int(node.kwargs["width"])) else: pen.setWidth(1) gpos = node.global_pos painter.setPen(pen) painter.setBrush(brush) if ("shape" in node.kwargs.keys()): if (node.kwargs["shape"] == "box"): painter.drawRect(gpos[0] - node.size[0] / 2, gpos[1] - node.size[1] / 2, node.size[0], node.size[1]) if (node.kwargs["shape"] == "circle"): painter.drawEllipse(gpos[0] - node.size[0] / 2, gpos[1] - node.size[1] / 2, node.size[0], node.size[1]) # Image as a node, this implementation checks to see if a # file path was provided in the shape parameter if (os.path.isfile(node.kwargs["shape"])): img_path = node.kwargs["shape"] painter.drawImage( QRect(gpos[0] - node.size[0] / 2, gpos[1] - node.size[1] / 2, node.size[0], node.size[1]), QImage(img_path)) else: painter.drawEllipse(gpos[0] - node.size[0] / 2, gpos[1] - node.size[1] / 2, node.size[0], node.size[1]) if ("label" in node.kwargs.keys()): painter.drawText(gpos[0] - node.size[0] / 2, gpos[1] - node.size[1] / 2, node.size[0], node.size[1], Qt.AlignCenter | Qt.AlignTop, node.kwargs["label"]) else: if (self.show_subgraphs): self.paintGraph(subgraph, painter) else: subgraph = node self.paintSubgraph(subgraph, painter, pen, brush)
class Drawer(QWidget): newPoint = pyqtSignal(QtCore.QPoint) def __init__(self, parent=None): QWidget.__init__(self, parent) self.path = QPainterPath() self.btn = QPushButton('classify', self) self.btn.clicked.connect(self.btn_event) self._left = False self.setStyleSheet("background-color:white;") self.img_data = None #print(dir(self.newPoint)) def btn_event(self): digit = load_and_predict.classify(self.img_data) buttonReply = QMessageBox.information( self, 'res', 'you are writing:{}'.format(digit), QMessageBox.Yes, QMessageBox.Yes) if buttonReply == QMessageBox.Yes: self.path = QPainterPath() self.update() def btnEvent2(self): print('hi') def paintEvent(self, event): p = QPen(QtCore.Qt.black) p.setWidth(20) painter = QPainter(self) painter.setPen(p) painter.drawPath(self.path) painter.end() def mousePressEvent(self, event): if event.button() == QtCore.Qt.LeftButton: self.path.moveTo(event.pos()) self._left = True pass elif event.button() == QtCore.Qt.RightButton: pass #print(dir(event)) self.update() def mouseMoveEvent(self, event): if self._left: self.path.lineTo(event.pos()) self.newPoint.emit(event.pos()) self.update() def mouseReleaseEvent(self, event): if event.button() == QtCore.Qt.LeftButton: px = self.grab() img = px.toImage() img = img.convertToFormat(QImage.Format_Grayscale8) file_name = 'tmp.jpg' img.save(file_name) cvMat = cv2.imread(file_name, -1) cvMat = 255 - cvMat self.img_data = cvMat self._left = False pass elif event.button() == QtCore.Qt.RightButton: self.path = QPainterPath() pass self.update() pass def sizeHint(self): return QtCore.QSize(300, 300)
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 drawGlyphPoints(painter, glyph, scale, rect, drawStartPoints=True, drawOnCurves=True, drawOffCurves=True, drawCoordinates=True, onCurveColor=None, otherColor=None, backgroundColor=None): layer = glyph.layer onCurveColor = None if layer is not None: if layer.color is not None: onCurveColor = colorToQColor(layer.color) if onCurveColor is None: 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) # off curve if drawOffCurves and outlineData["offCurvePoints"]: # lines 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) # 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 point["selected"]: selectedPath.addPath(pointPath) else: path.addPath(pointPath) pen = QPen(otherColor) pen.setWidthF(3.0 * scale) painter.setPen(pen) painter.drawPath(path) painter.fillPath(path, QBrush(backgroundColor)) painter.drawPath(selectedPath) painter.fillPath(selectedPath, QBrush(otherColor)) 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 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() # coordinates if drawCoordinates: otherColor = QColor(otherColor) otherColor.setAlphaF(otherColor.alphaF() * .6) painter.save() painter.setPen(otherColor) 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 paintEvent(self, ev: QtGui.QPaintEvent): p = QPainter(self) option = QStyleOptionButton() option.initFrom(self) #background p.fillRect(0, 0, self.width(), self.height(), QColor('#131722')) #x-grid path = QPainterPath() x = self.moving.x() y = self.moving.y() path.moveTo(x + -4, 0 + y) path.lineTo(x + -4, 233 + +y) path.moveTo(x + 93, 0 + y) path.lineTo(x + 93, 233 + +y) path.moveTo(x + 190, 0 + y) path.lineTo(x + 190, 233 + +y) path.moveTo(x + 287, 0 + y) path.lineTo(x + 287, 233 + +y) path.moveTo(x + 384, 0 + y) path.lineTo(x + 384, 233 + +y) p.setPen(QColor('#363c4e')) p.drawPath(path) #y-grid path = QPainterPath() path.moveTo(x + 0, 2 + y) path.lineTo(x + 440, 2 + y) path.moveTo(x + 0, 40 + y) path.lineTo(x + 440, 40 + y) path.moveTo(x + 0, 77 + y) path.lineTo(x + 440, 77 + y) path.moveTo(x + 0, 114 + y) path.lineTo(x + 440, 114 + y) path.moveTo(x + 0, 152 + y) path.lineTo(x + 440, 152 + y) path.moveTo(x + 0, 189 + y) path.lineTo(x + 440, 189 + y) path.moveTo(x + 0, 226 + y) path.lineTo(x + 440, 226 + y) p.setPen(QColor('#363c4e')) p.drawPath(path) # candle p.fillRect(44, 40, 1, 0, QColor('#336854')) p.fillRect(34, 35, 1, 9, QColor('#336854')) p.fillRect(24, 12, 1, 37, QColor('#336854')) p.fillRect(15, 44, 1, 28, QColor('#336854')) p.fillRect(5, 68, 1, 23, QColor('#336854')) p.fillRect(-5, 12, 1, 102, QColor('#336854')) p.fillRect(41, 40, 7, 1, QColor('#53b987')) p.fillRect(31, 40, 7, 1, QColor('#53b987')) p.fillRect(21, 40, 7, 5, QColor('#53b987')) p.fillRect(12, 44, 7, 29, QColor('#53b987')) p.fillRect(2, 72, 7, 15, QColor('#53b987')) p.fillRect(-8, 86, 7, 29, QColor('#53b987')) if option.state & QStyle.State_MouseOver: self.setCursor(Qt.PointingHandCursor) # print(self.width(), self.height()) #price path = QPainterPath() path.moveTo(0, 40) path.lineTo(440, 40) pen = p.pen() pen.setStyle(Qt.DashDotLine) pen.setColor(QColor("#53b987")) p.setPen(pen) p.drawPath(path) #mouse path = QPainterPath() path.moveTo(0, self.pos.y()) path.lineTo(self.width(), self.pos.y()) path.moveTo(self.pos.x(), 0) path.lineTo(self.pos.x(), self.height()) p.setPen(Qt.red) p.drawPath(path)
def updateFloatPath(self, point=None): """ Draws a quad curve from the edge of the fromBase to the top or bottom of the toBase (q5), and finally to the center of the toBase (toBaseEndpoint). If floatPos!=None, this is a floatingXover and floatPos is the destination point (where the mouse is) while toHelix, toIndex are potentially None and represent the base at floatPos. Args: point (None, optional): Description """ node3 = self._node3 node5 = self._node5 bw = _BASE_WIDTH vhi5 = self._virtual_helix_item nucleicacid_part_item = vhi5.partItem() pt5 = vhi5.mapToItem(nucleicacid_part_item, *node5.floatPoint()) n5_is_forward = node5.is_forward # Enter/exit are relative to the direction that the path travels # overall. five_enter_pt = pt5 + QPointF(0 if n5_is_forward else 1, .5)*bw five_center_pt = pt5 + QPointF(.5, .5)*bw five_exit_pt = pt5 + QPointF(.5, 0 if n5_is_forward else 1)*bw vhi3 = node3.virtualHelixItem() if point: pt3 = point n3_is_forward = True same_strand = False same_parity = False three_enter_pt = three_center_pt = three_exit_pt = pt3 else: pt3 = vhi3.mapToItem(nucleicacid_part_item, *node3.point()) n3_is_forward = node3.is_forward same_strand = (n5_is_forward == n3_is_forward) and vhi3 == vhi5 same_parity = n5_is_forward == n3_is_forward three_enter_pt = pt3 + QPointF(.5, 0 if n3_is_forward else 1)*bw three_center_pt = pt3 + QPointF(.5, .5)*bw three_exit_pt = pt3 + QPointF(1 if n3_is_forward else 0, .5)*bw c1 = QPointF() # case 1: same strand if same_strand: dx = abs(three_enter_pt.x() - five_exit_pt.x()) c1.setX(0.5 * (five_exit_pt.x() + three_enter_pt.x())) if n5_is_forward: c1.setY(five_exit_pt.y() - _yScale * dx) else: c1.setY(five_exit_pt.y() + _yScale * dx) # case 2: same parity elif same_parity: dy = abs(three_enter_pt.y() - five_exit_pt.y()) c1.setX(five_exit_pt.x() + _xScale * dy) c1.setY(0.5 * (five_exit_pt.y() + three_enter_pt.y())) # case 3: different parity else: if n5_is_forward: c1.setX(five_exit_pt.x() - _xScale * abs(three_enter_pt.y() - five_exit_pt.y())) else: c1.setX(five_exit_pt.x() + _xScale * abs(three_enter_pt.y() - five_exit_pt.y())) c1.setY(0.5 * (five_exit_pt.y() + three_enter_pt.y())) # Construct painter path painterpath = QPainterPath() painterpath.moveTo(five_enter_pt) painterpath.lineTo(five_center_pt) painterpath.lineTo(five_exit_pt) painterpath.quadTo(c1, three_enter_pt) painterpath.lineTo(three_center_pt) painterpath.lineTo(three_exit_pt) self.setPath(painterpath) self._updateFloatPen()
from PyQt5.QtCore import Qt from PyQt5.QtGui import QColor, QKeySequence, QPainterPath from PyQt5.QtWidgets import QApplication from trufont.drawingTools.baseTool import BaseTool import unicodedata _path = QPainterPath() _path.moveTo(5.29, 17.96) _path.lineTo(6.94, 17.96) _path.lineTo(7.36, 21.5) _path.lineTo(7.78, 21.95) _path.lineTo(12.4, 21.95) _path.lineTo(12.4, 6.35) _path.lineTo(11.86, 5.93) _path.lineTo(9.7, 5.78) _path.lineTo(9.7, 4.45) _path.lineTo(18.3, 4.45) _path.lineTo(18.3, 5.78) _path.lineTo(16.14, 5.93) _path.lineTo(15.6, 6.35) _path.lineTo(15.6, 21.95) _path.lineTo(20.22, 21.95) _path.lineTo(20.64, 21.5) _path.lineTo(21.06, 17.96) _path.lineTo(22.71, 17.96) _path.lineTo(22.71, 23.58) _path.lineTo(5.29, 23.58) _path.closeSubpath() def _isUnicodeChar(text):
def createArrowBackground(self, transform): scaledRect = transform.mapRect( QRect(0, 0, self.logicalSize.width(), self.logicalSize.height())) image = QImage(scaledRect.width(), scaledRect.height(), QImage.Format_ARGB32_Premultiplied) image.fill(QColor(0, 0, 0, 0).rgba()) painter = QPainter(image) painter.setRenderHint(QPainter.SmoothPixmapTransform) painter.setRenderHint(QPainter.Antialiasing) painter.setPen(Qt.NoPen) if Colors.useEightBitPalette: painter.setPen(QColor(120, 120, 120)) if self.pressed: painter.setBrush(QColor(60, 60, 60)) elif self.highlighted: painter.setBrush(QColor(100, 100, 100)) else: painter.setBrush(QColor(80, 80, 80)) else: outlinebrush = QLinearGradient(0, 0, 0, scaledRect.height()) brush = QLinearGradient(0, 0, 0, scaledRect.height()) brush.setSpread(QLinearGradient.PadSpread) highlight = QColor(255, 255, 255, 70) shadow = QColor(0, 0, 0, 70) sunken = QColor(220, 220, 220, 30) normal1 = QColor(200, 170, 160, 50) normal2 = QColor(50, 10, 0, 50) if self.pressed: outlinebrush.setColorAt(0, shadow) outlinebrush.setColorAt(1, highlight) brush.setColorAt(0, sunken) painter.setPen(Qt.NoPen) else: outlinebrush.setColorAt(1, shadow) outlinebrush.setColorAt(0, highlight) brush.setColorAt(0, normal1) if not self.highlighted: brush.setColorAt(1, normal2) painter.setPen(QPen(outlinebrush, 1)) painter.setBrush(brush) painter.draw_rect(0, 0, scaledRect.width(), scaledRect.height()) xOff = scaledRect.width() / 2 yOff = scaledRect.height() / 2 sizex = 3.0 * transform.m11() sizey = 1.5 * transform.m22() if self.type == TextButton.UP: sizey *= -1 path = QPainterPath() path.moveTo(xOff, yOff + (5 * sizey)) path.lineTo(xOff - (4 * sizex), yOff - (3 * sizey)) path.lineTo(xOff + (4 * sizex), yOff - (3 * sizey)) path.lineTo(xOff, yOff + (5 * sizey)) painter.draw_path(path) return image
def mousePressEvent(self, evt: QtGui.QMouseEvent) -> None: image_rect: QRectF = self._pixmap.boundingRect() mouse_pos = self.mapToScene(evt.pos()) if evt.buttons() == QtCore.Qt.LeftButton: if self.current_tool == SELECTION_TOOL.BOX: # create rectangle self.setDragMode(QGraphicsView.NoDrag) self._rectangle_tool_origin = evt.pos() geometry = QRect(self._rectangle_tool_origin, QSize()) self._rectangle_tool_picker.setGeometry(geometry) self._rectangle_tool_picker.show() elif self.current_tool == SELECTION_TOOL.POLYGON: if image_rect.contains(mouse_pos): if self._current_polygon is None: self._current_polygon = EditablePolygon() self._current_polygon.label = self._current_label self._current_polygon.tag = self._dataset self._current_polygon.signals.deleted.connect( self.delete_polygon_slot) self._scene.addItem(self._current_polygon) self._current_polygon.addPoint(mouse_pos) else: self._current_polygon.addPoint(mouse_pos) elif self.current_tool == SELECTION_TOOL.ELLIPSE: if image_rect.contains(mouse_pos): self.setDragMode(QGraphicsView.NoDrag) ellipse_rec = QtCore.QRectF(mouse_pos.x(), mouse_pos.y(), 0, 0) self._current_ellipse = EditableEllipse() self._current_ellipse.tag = self.dataset self._current_ellipse.label = self._current_label self._current_ellipse.setRect(ellipse_rec) self._scene.addItem(self._current_ellipse) elif self.current_tool == SELECTION_TOOL.FREE: # consider only the points into the image if image_rect.contains(mouse_pos): self.setDragMode(QGraphicsView.NoDrag) self._last_point_drawn = mouse_pos self._current_free_path = QGraphicsPathItem() self._current_free_path.setOpacity(0.6) self._current_free_path.setPen(self._free_Path_pen) painter = QPainterPath() painter.moveTo(self._last_point_drawn) self._current_free_path.setPath(painter) self._scene.addItem(self._current_free_path) elif self.current_tool == SELECTION_TOOL.EXTREME_POINTS: if image_rect.contains(mouse_pos): if not self._extreme_points.full(): def delete_point(idx): del self._extreme_points.queue[idx] idx = self._extreme_points.qsize() editable_pt = EditablePolygonPoint(idx) editable_pt.signals.deleted.connect(delete_point) editable_pt.setPos(mouse_pos) self._scene.addItem(editable_pt) self._extreme_points.put(editable_pt) else: self.setDragMode(QGraphicsView.ScrollHandDrag) super(ImageViewer, self).mousePressEvent(evt)
def _updatePath(self, strand5p): """ Draws a quad curve from the edge of the fromBase to the top or bottom of the toBase (q5), and finally to the center of the toBase (toBaseEndpoint). If floatPos!=None, this is a floatingXover and floatPos is the destination point (where the mouse is) while toHelix, toIndex are potentially None and represent the base at floatPos. Args: strand5p (TYPE): Description """ group = self.group() self.tempReparent() node3 = self._node3 node5 = self._node5 bw = _BASE_WIDTH parent = self.partItem() vhi5 = self._virtual_helix_item pt5 = vhi5.mapToItem(parent, *node5.point()) n5_is_forward = node5.is_forward vhi3 = node3.virtualHelixItem() pt3 = vhi3.mapToItem(parent, *node3.point()) n3_is_forward = node3.is_forward same_strand = (n5_is_forward == n3_is_forward) and (vhi3 == vhi5) same_parity = n5_is_forward == n3_is_forward # Enter/exit are relative to the direction that the path travels # overall. five_enter_pt = pt5 + QPointF(0 if n5_is_forward else 1, .5) * bw five_center_pt = pt5 + QPointF(.5, .5) * bw # five_exit_pt = pt5 + QPointF(.85 if n5_is_forward else .15, 0 if n5_is_forward else 1)*bw five_exit_pt = pt5 + QPointF(.5 if n5_is_forward else .5, 0 if n5_is_forward else 1) * bw # three_enter_pt = pt3 + QPointF(.15 if n3_is_forward else .85, 0 if n3_is_forward else 1)*bw three_enter_pt = pt3 + QPointF(.5 if n3_is_forward else .5, 0 if n3_is_forward else 1) * bw three_center_pt = pt3 + QPointF(.5, .5) * bw three_exit_pt = pt3 + QPointF(1 if n3_is_forward else 0, .5) * bw c1 = QPointF() # case 1: same strand if same_strand: dx = abs(three_enter_pt.x() - five_exit_pt.x()) c1.setX(0.5 * (five_exit_pt.x() + three_enter_pt.x())) if n5_is_forward: c1.setY(five_exit_pt.y() - _Y_SCALE * dx) else: c1.setY(five_exit_pt.y() + _Y_SCALE * dx) # case 2: same parity elif same_parity: dy = abs(three_enter_pt.y() - five_exit_pt.y()) c1.setX(five_exit_pt.x() + _X_SCALE * dy) c1.setY(0.5 * (five_exit_pt.y() + three_enter_pt.y())) # case 3: different parity else: if n5_is_forward: c1.setX(five_exit_pt.x() - _X_SCALE * abs(three_enter_pt.y() - five_exit_pt.y())) else: c1.setX(five_exit_pt.x() + _X_SCALE * abs(three_enter_pt.y() - five_exit_pt.y())) c1.setY(0.5 * (five_exit_pt.y() + three_enter_pt.y())) # Construct painter path painterpath = QPainterPath() painterpath.moveTo(five_enter_pt) painterpath.lineTo(five_center_pt) painterpath.lineTo(five_exit_pt) # The xover5's non-crossing-over end (3') has a connection painterpath.quadTo(c1, three_enter_pt) painterpath.lineTo(three_center_pt) painterpath.lineTo(three_exit_pt) tempR = painterpath.boundingRect() tempR.adjust(-bw / 2, 0, bw, 0) self._click_area.setRect(tempR) self.setPath(painterpath) node3.updatePositionAndAppearance() node5.updatePositionAndAppearance() if group: group.addToGroup(self) self._updateColor(strand5p)
def createCurveIcons(self): pix = QPixmap(self.m_iconSize) painter = QPainter() gradient = QLinearGradient(0, 0, 0, self.m_iconSize.height()) gradient.setColorAt(0.0, QColor(240, 240, 240)) gradient.setColorAt(1.0, QColor(224, 224, 224)) brush = QBrush(gradient) # The original C++ code uses undocumented calls to get the names of the # different curve types. We do the Python equivalant (but without # cheating). curve_types = [(n, c) for n, c in QEasingCurve.__dict__.items() if isinstance(c, QEasingCurve.Type) and c != QEasingCurve.Custom] curve_types.sort(key=lambda ct: ct[1]) painter.begin(pix) for curve_name, curve_type in curve_types: painter.fillRect(QRect(QPoint(0, 0), self.m_iconSize), brush) curve = QEasingCurve(curve_type) if curve_type == QEasingCurve.BezierSpline: curve.addCubicBezierSegment(QPointF(0.4, 0.1), QPointF(0.6, 0.9), QPointF(1.0, 1.0)) elif curve_type == QEasingCurve.TCBSpline: curve.addTCBSegment(QPointF(0.0, 0.0), 0, 0, 0) curve.addTCBSegment(QPointF(0.3, 0.4), 0.2, 1, -0.2) curve.addTCBSegment(QPointF(0.7, 0.6), -0.2, 1, 0.2) curve.addTCBSegment(QPointF(1.0, 1.0), 0, 0, 0) painter.setPen(QColor(0, 0, 255, 64)) xAxis = self.m_iconSize.height() / 1.5 yAxis = self.m_iconSize.width() / 3.0 painter.drawLine(0, xAxis, self.m_iconSize.width(), xAxis) painter.drawLine(yAxis, 0, yAxis, self.m_iconSize.height()) curveScale = self.m_iconSize.height() / 2.0; painter.setPen(Qt.NoPen) # Start point. painter.setBrush(Qt.red) start = QPoint(yAxis, xAxis - curveScale * curve.valueForProgress(0)) painter.drawRect(start.x() - 1, start.y() - 1, 3, 3) # End point. painter.setBrush(Qt.blue) end = QPoint(yAxis + curveScale, xAxis - curveScale * curve.valueForProgress(1)) painter.drawRect(end.x() - 1, end.y() - 1, 3, 3) curvePath = QPainterPath() curvePath.moveTo(QPointF(start)) t = 0.0 while t <= 1.0: to = QPointF(yAxis + curveScale * t, xAxis - curveScale * curve.valueForProgress(t)) curvePath.lineTo(to) t += 1.0 / curveScale painter.setRenderHint(QPainter.Antialiasing, True) painter.strokePath(curvePath, QColor(32, 32, 32)) painter.setRenderHint(QPainter.Antialiasing, False) item = QListWidgetItem() item.setIcon(QIcon(pix)) item.setText(curve_name) self.m_ui.easingCurvePicker.addItem(item) painter.end()
class SortingBox(QWidget): circle_count = square_count = triangle_count = 1 def __init__(self): super(SortingBox, self).__init__() self.circlePath = QPainterPath() self.squarePath = QPainterPath() self.trianglePath = QPainterPath() self.shapeItems = [] self.previousPosition = QPoint() self.setMouseTracking(True) self.setBackgroundRole(QPalette.Base) self.itemInMotion = None self.newCircleButton = self.createToolButton( "New Circle", QIcon(':/images/circle.png'), self.createNewCircle) self.newSquareButton = self.createToolButton( "New Square", QIcon(':/images/square.png'), self.createNewSquare) self.newTriangleButton = self.createToolButton( "New Triangle", QIcon(':/images/triangle.png'), self.createNewTriangle) self.circlePath.addEllipse(0, 0, 100, 100) self.squarePath.addRect(0, 0, 100, 100) x = self.trianglePath.currentPosition().x() y = self.trianglePath.currentPosition().y() self.trianglePath.moveTo(x + 120 / 2, y) self.trianglePath.lineTo(0, 100) self.trianglePath.lineTo(120, 100) self.trianglePath.lineTo(x + 120 / 2, y) self.setWindowTitle("Tooltips") self.resize(500, 300) self.createShapeItem(self.circlePath, "Circle", self.initialItemPosition(self.circlePath), self.initialItemColor()) self.createShapeItem(self.squarePath, "Square", self.initialItemPosition(self.squarePath), self.initialItemColor()) self.createShapeItem(self.trianglePath, "Triangle", self.initialItemPosition(self.trianglePath), self.initialItemColor()) def event(self, event): if event.type() == QEvent.ToolTip: helpEvent = event index = self.itemAt(helpEvent.pos()) if index != -1: QToolTip.showText(helpEvent.globalPos(), self.shapeItems[index].toolTip()) else: QToolTip.hideText() event.ignore() return True return super(SortingBox, self).event(event) def resizeEvent(self, event): margin = self.style().pixelMetric(QStyle.PM_DefaultTopLevelMargin) x = self.width() - margin y = self.height() - margin y = self.updateButtonGeometry(self.newCircleButton, x, y) y = self.updateButtonGeometry(self.newSquareButton, x, y) self.updateButtonGeometry(self.newTriangleButton, x, y) def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) for shapeItem in self.shapeItems: painter.translate(shapeItem.position()) painter.setBrush(shapeItem.color()) painter.draw_path(shapeItem.path()) painter.translate(-shapeItem.position()) def mousePressEvent(self, event): if event.button() == Qt.LeftButton: index = self.itemAt(event.pos()) if index != -1: self.itemInMotion = self.shapeItems[index] self.previousPosition = event.pos() value = self.shapeItems[index] del self.shapeItems[index] self.shapeItems.insert(len(self.shapeItems) - 1, value) self.update() def mouseMoveEvent(self, event): if (event.buttons() & Qt.LeftButton) and self.itemInMotion: self.moveItemTo(event.pos()) def mouseReleaseEvent(self, event): if (event.button() == Qt.LeftButton) and self.itemInMotion: self.moveItemTo(event.pos()) self.itemInMotion = None def createNewCircle(self): SortingBox.circle_count += 1 self.createShapeItem(self.circlePath, "Circle <%d>" % SortingBox.circle_count, self.randomItemPosition(), self.randomItemColor()) def createNewSquare(self): SortingBox.square_count += 1 self.createShapeItem(self.squarePath, "Square <%d>" % SortingBox.square_count, self.randomItemPosition(), self.randomItemColor()) def createNewTriangle(self): SortingBox.triangle_count += 1 self.createShapeItem(self.trianglePath, "Triangle <%d>" % SortingBox.triangle_count, self.randomItemPosition(), self.randomItemColor()) def itemAt(self, pos): for i in range(len(self.shapeItems) - 1, -1, -1): item = self.shapeItems[i] if item.path().contains(QPointF(pos - item.position())): return i return -1 def moveItemTo(self, pos): offset = pos - self.previousPosition self.itemInMotion.setPosition(self.itemInMotion.position() + offset) self.previousPosition = QPoint(pos) self.update() def updateButtonGeometry(self, button, x, y): size = button.sizeHint() button.setGeometry(x - size.width(), y - size.height(), size.width(), size.height()) return y - size.height() - self.style().pixelMetric( QStyle.PM_DefaultLayoutSpacing) def createShapeItem(self, path, toolTip, pos, color): shapeItem = ShapeItem() shapeItem.setPath(path) shapeItem.setToolTip(toolTip) shapeItem.setPosition(pos) shapeItem.setColor(color) self.shapeItems.append(shapeItem) self.update() def createToolButton(self, toolTip, icon, member): button = QToolButton(self) button.setToolTip(toolTip) button.setIcon(icon) button.setIconSize(QSize(32, 32)) button.clicked.connect(member) return button def initialItemPosition(self, path): y = (self.height() - path.controlPointRect().height()) / 2 if len(self.shapeItems) == 0: x = ((3 * self.width()) / 2 - path.controlPointRect().width()) / 2 else: x = (self.width() / len(self.shapeItems) - path.controlPointRect().width()) / 2 return QPoint(x, y) def randomItemPosition(self): x = random.randint(0, self.width() - 120) y = random.randint(0, self.height() - 120) return QPoint(x, y) def initialItemColor(self): hue = ((len(self.shapeItems) + 1) * 85) % 256 return QColor.fromHsv(hue, 255, 190) def randomItemColor(self): return QColor.fromHsv(random.randint(0, 256), 255, 190)
def draw_bg(self, p): w = self.width() h = self.height() col = (w - self.padLeft - self.padRight)/3 row = (h - self.padDown - self.padTop)/5 p.setPen(QPen(QColor(self.bgColor), 10, Qt.SolidLine, Qt.FlatCap, Qt.RoundJoin)) p.fillRect(0, 0, self.width(), self.height(), QColor(self.bgColor)) p.setPen(QPen(QColor(self.lineColor), 2, Qt.SolidLine, Qt.FlatCap, Qt.RoundJoin)) path = QPainterPath() path.moveTo(self.padLeft, self.padTop) path.lineTo(w - self.padRight, self.padTop) path.lineTo(w - self.padRight, h - self.padDown) path.lineTo(self.padLeft, h - self.padDown) path.lineTo(self.padLeft, self.padTop) path.moveTo(self.padLeft + col, self.padTop) path.lineTo(self.padLeft + col, h - self.padDown) path.moveTo(self.padLeft + col*2, self.padTop) path.lineTo(self.padLeft + col*2, h - self.padDown) path.moveTo(self.padLeft, self.padTop + row) path.lineTo(w - self.padRight, self.padTop + row) path.moveTo(self.padLeft, self.padTop + row*2) path.lineTo(w - self.padRight, self.padTop + row*2) path.moveTo(self.padLeft, self.padTop + row*3) path.lineTo(w - self.padRight, self.padTop + row*3) path.moveTo(self.padLeft, self.padTop + row*4) path.lineTo(w - self.padRight, self.padTop + row*4) p.drawPath(path)
from PyQt5.QtCore import pyqtSignal, QEvent, QRect, QSize, Qt from PyQt5.QtGui import QColor, QPainter, QPainterPath from PyQt5.QtWidgets import QSizePolicy, QToolTip, QWidget __all__ = ["TabWidget"] sidePadding = 9 spacing = 2 topPadding = bottomPadding = 5 crossMargin = sidePadding crossSize = 7 cross = QPainterPath() cross.moveTo(0.38, 0.38) cross.lineTo(9.63, 9.63) cross.moveTo(0.38, 9.63) cross.lineTo(9.63, 0.38) class TabWidget(QWidget): """ # TODO: RTL support? """ currentTabChanged = pyqtSignal(int) tabRemoved = pyqtSignal(int) def __init__(self, parent=None): super().__init__(parent) self.setMouseTracking(True) self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Maximum)
def createHoneycombGrid(self, part_item, radius, bounds): """Instantiate an area of griditems arranged on a honeycomb lattice. 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 x_l = x_l + HoneycombDnaPart.PAD_GRID_XL x_h = x_h + HoneycombDnaPart.PAD_GRID_XH y_h = y_h + HoneycombDnaPart.PAD_GRID_YL y_l = y_l + HoneycombDnaPart.PAD_GRID_YH 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) redo_neighbors = (row_l, col_l, row_h, col_h) != self.previous_grid_bounds or\ self.previous_grid_type != self.grid_type self.previous_grid_type = self.grid_type path = QPainterPath() is_pen_down = False draw_lines = self.draw_lines if redo_neighbors: point_coordinates = dict() neighbor_map = dict() self.points_dict = dict() for row in range(row_l, row_h): for column in range(col_l, col_h + 1): x, y = doLattice(radius, row, column, 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, coord=(row, column)) if self._draw_gridpoint_coordinates: font = QFont(styles.THE_FONT) path.addText(x - 10, -y + 5, font, "%s,%s" % (-row, column)) pt.setPen( getPenObj(styles.GRAY_STROKE, styles.EMPTY_HELIX_STROKE_WIDTH)) # if x == 0 and y == 0: # pt.setBrush(getBrushObj(Qt.gray)) points.append(pt) self.points_dict[(-row, column)] = pt if redo_neighbors: point_coordinates[(-row, column)] = (x, -y) # This is reversed since the Y is mirrored if not HoneycombDnaPart.isEvenParity(row, column): neighbor_map[(-row, column)] = [(-row - 1, column), (-row, column + 1), (-row, column - 1)] else: neighbor_map[(-row, column)] = [(-row + 1, column), (-row, column - 1), (-row, column + 1)] self.previous_grid_bounds = (row_l, col_l, row_h, col_h) is_pen_down = False if draw_lines: for column in range(col_l, col_h + 1): for row in range(row_l, row_h): x, y = doLattice(radius, row, column, scale_factor=sf) if is_pen_down and isEven(row, column): 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._path.setPath(path) if redo_neighbors: self.part_item.setNeighborMap(neighbor_map=neighbor_map) self.part_item.setPointMap(point_map=point_coordinates)
def drawBezierCurve(self, qp): path = QPainterPath() path.moveTo(30, 30) path.cubicTo(30, 30, 200, 150, 350, 30) qp.drawPath(path)
def draw_fretboard(self, scene, posX, posY): # Real 22 frets Gibson guitar scale length SCALE_LENGTH = [ 0, 35.28, 68.59, 100.02, 129.69, 157.69, 184.13, 209.08, 232.63, 254.85, 275.83, 295.63, 314.32, 331.98, 348.61, 364.34, 379.17, 393.17, 406.39, 418.86, 430.64, 441.75, 452.24 ] # Increase them for better representation self.scaleLength = [i * 3 for i in SCALE_LENGTH] # Distance between two strings DISTANCE = 34 # Starting cooridnates x = posX y = posY # Note coordinates of the strings # Open position coordinates self.sNoteCoordinate1 = [QPoint(x, y)] self.sNoteCoordinate2 = [QPoint(x, y + DISTANCE)] self.sNoteCoordinate3 = [QPoint(x, y + DISTANCE * 2)] self.sNoteCoordinate4 = [QPoint(x, y + DISTANCE * 3)] self.sNoteCoordinate5 = [QPoint(x, y + DISTANCE * 4)] self.sNoteCoordinate6 = [QPoint(x, y + DISTANCE * 5)] # Offset from the open position OFFSET = 30 # The remaining position coordinates for i in range(len(self.scaleLength) - 1): x = self.scaleLength[i] + ( (self.scaleLength[i + 1] - self.scaleLength[i]) / 2) + OFFSET - 14 self.sNoteCoordinate1.append(QPoint(x, y)) self.sNoteCoordinate2.append(QPoint(x, y + DISTANCE)) self.sNoteCoordinate3.append(QPoint(x, y + DISTANCE * 2)) self.sNoteCoordinate4.append(QPoint(x, y + DISTANCE * 3)) self.sNoteCoordinate5.append(QPoint(x, y + DISTANCE * 4)) self.sNoteCoordinate6.append(QPoint(x, y + DISTANCE * 5)) # Store the strings in a list for better iteration self.sNoteCoordinates = [] self.sNoteCoordinates.append(self.sNoteCoordinate6) self.sNoteCoordinates.append(self.sNoteCoordinate5) self.sNoteCoordinates.append(self.sNoteCoordinate4) self.sNoteCoordinates.append(self.sNoteCoordinate3) self.sNoteCoordinates.append(self.sNoteCoordinate2) self.sNoteCoordinates.append(self.sNoteCoordinate1) # Starting guitar string cooridnates x = posX y = posY # Draw outer fretboard box whitePen = QPen(Qt.white) whitePen.setWidth(5) whitePen.setJoinStyle(Qt.MiterJoin) brownBrush = QBrush(QColor(75, 30, 0)) rect1 = QRectF(x, y, self.scaleLength[-1] + OFFSET, DISTANCE * 6) scene.addRect(rect1, whitePen, brownBrush) whiteBrush = QBrush(Qt.white) rect2 = QRectF(x, y, x + OFFSET, DISTANCE * 6) scene.addRect(rect2, whitePen, whiteBrush) # Starting inlay cooridnates x = posX y = posY # Trapezoid inlay color gradient = QLinearGradient(0, 0, 50, 50) gradient.setColorAt(0.0, QColor(200, 200, 200)) gradient.setColorAt(0.5, Qt.white) gradient.setColorAt(1.0, QColor(200, 200, 200)) gradient.setSpread(QGradient.ReflectSpread) grayPen = QPen(QColor(216, 216, 216)) grayBrush = QBrush(gradient) # The 3rd, 5th, 7th and 9th inlay leftTrim = 5 rightTrim = 40 j = 2 for i in range(4): x1 = x + self.scaleLength[j] + ( (self.scaleLength[j + 1] - self.scaleLength[j]) / 2) + leftTrim x2 = x + self.scaleLength[j + 1] + ( (self.scaleLength[i + 2] - self.scaleLength[i + 1]) / 2) - rightTrim path = QPainterPath() path.moveTo(x1, y + DISTANCE) path.lineTo(x1, y + DISTANCE * 5) path.lineTo(x2, y + DISTANCE * 5 - 20) path.lineTo(x2, y + DISTANCE + 15) path.closeSubpath() scene.addPath(path, grayPen, grayBrush) leftTrim += 2 rightTrim -= 5 j += 2 # The 12th inlay leftTrim = 15 rightTrim = 8 x1 = x + self.scaleLength[11] + ( (self.scaleLength[12] - self.scaleLength[11]) / 2) + leftTrim x2 = x + self.scaleLength[12] + ( (self.scaleLength[13] - self.scaleLength[12]) / 2) - rightTrim path = QPainterPath() path.moveTo(x1, y + DISTANCE) path.lineTo(x1, y + DISTANCE * 5) path.lineTo(x2, y + DISTANCE * 5 - 20) path.lineTo(x2, y + DISTANCE + 15) path.closeSubpath() scene.addPath(path, grayPen, grayBrush) # The 15th, 17th, 19th and 21th inlay leftTrim = 15 rightTrim = 28 j = 14 for i in range(4): x1 = x + self.scaleLength[j] + ( (self.scaleLength[j + 1] - self.scaleLength[j]) / 2) + leftTrim x2 = x + self.scaleLength[j + 1] + ( (self.scaleLength[i + 2] - self.scaleLength[i + 1]) / 2) - rightTrim path = QPainterPath() path.moveTo(x1, y + DISTANCE) path.lineTo(x1, y + DISTANCE * 5) path.lineTo(x2, y + DISTANCE * 5 - 20) path.lineTo(x2, y + DISTANCE + 15) path.closeSubpath() scene.addPath(path, grayPen, grayBrush) leftTrim += 2 rightTrim -= 1 + (i + 1) j += 2 # Starting guitar string cooridnates x = posX y = posY - 20 # Draw the guitar strings s = QLineF(x, y, x + self.scaleLength[-1] + OFFSET, y) whitePen = QPen(Qt.white) whitePen.setWidth(1) startHPos = DISTANCE stringWidth = 1 for i in range(6): whitePen.setWidth(stringWidth) guitarString = scene.addLine(s, whitePen) guitarString.setPos(0, startHPos) startHPos += DISTANCE stringWidth += 0.4 # Starting fret cooridnates x = posX y = posY # Draw the frets fretPen = QPen(Qt.white) fretPen.setWidth(5) fret = QLineF(x + OFFSET, y, x + OFFSET, y + DISTANCE * 6 - 5) for i in range(len(self.scaleLength)): guitarFret = scene.addLine(fret, fretPen) guitarFret.setPos(self.scaleLength[i], 0) # Add fret numbers for i in range(22): fret_num = QGraphicsTextItem(str(i)) fret_num.setFont(QFont("Verdana", 20)) fret_num.setDefaultTextColor(QColor(Qt.red)) fret_num.setPos(self.scaleLength[i], 220) scene.addItem(fret_num)
def paintEvent(self, event): metrics = QFontMetrics(self.font) fw = metrics.width("0000000") fh = metrics.height() ascent = metrics.ascent() w, h = self.width(), self.height() painter = QPainter(self) painter.setFont(self.font) blackpen = QPen(Qt.black, 1) greypen = QPen(Qt.gray, 1) painter.setPen(blackpen) fill = QBrush(QColor(255, 255, 255)) painter.fillRect(QRect(fw, 0, w - fw - 1, h - fh), fill) if self.A.shape[1]: X, Y = numpy.moveaxis(self.A[:, -w // 2:], 2, 0) Ymin = min(0, Y.min()) Ymax = Y.max() maxticks = int((h - fh) / (1.5 * fh)) for k in count(0): if 2**k * maxticks >= Ymax: break ticks = Ymax / 2**k ticks = int(ticks + (-ticks) % 1) Ymax = ticks * 2**k Xmax = X.max() Xmin = Xmax - w / 2 for x in range(int(Xmin + (120 - Xmin) % 120), int(Xmax), 120): if x < 0: continue u = (w - fw) * (x - Xmin) / (Xmax - Xmin) + fw painter.setPen(greypen) painter.drawLine(u, 0, u, h - fh) painter.setPen(blackpen) sw = metrics.width(str(x)) if u - sw // 2 > fw and u + sw // 2 < w: painter.drawText(u - sw // 2, h, str(x)) for y in range(0, int(Ymax), 2**k): v = h - fh - (h - fh) * (y - Ymin) / (Ymax - Ymin) painter.setPen(greypen) painter.drawLine(fw, v, w, v) painter.setPen(blackpen) sw = metrics.width(str(y)) painter.drawText(fw - sw - 4, v + ascent / 3, str(y)) for pen, row in zip(self.pens, self.A): X, Y = row[-w // 2:].transpose() U = (w - fw) * (X - Xmin) / (Xmax - Xmin) + fw V = h - fh - (h - fh) * (Y - Ymin) / (Ymax - Ymin) painter.setPen(pen) path = QPainterPath() painter.setRenderHint(QPainter.Antialiasing) path.moveTo(U[0], V[0]) for x, y in zip(U[1:], V[1:]): path.lineTo(x, y) painter.drawPath(path) painter.setPen(blackpen) painter.drawRect(QRect(fw, 0, w - fw - 1, h - fh))
def drawGlyphPoints(painter, glyph, scale, drawStartPoints=True, drawOnCurves=True, drawOffCurves=True, drawCoordinates=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 = [] # 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"]: 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) 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) 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() painter.setPen(otherColor) 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 + 6 * scale 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()
from trufont.controls.propertiesView import PropertiesView from trufont.controls.statusBar import StatusBar from trufont.controls.tabWidget import TabWidget from trufont.controls.toolBar import ToolBar from trufont.objects import settings from trufont.objects.menu import Entries from trufont.tools import errorReports, platformSpecific from trufont.tools.uiMethods import deleteUISelection, removeUIGlyphElements from trufont.windows.fontFeaturesWindow import FontFeaturesWindow from trufont.windows.fontInfoWindow import FontInfoWindow from trufont.windows.groupsWindow import GroupsWindow from trufont.windows.kerningWindow import KerningWindow from trufont.windows.metricsWindow import MetricsWindow _path = QPainterPath() _path.moveTo(5, 8) _path.lineTo(23, 8) _path.lineTo(23, 10) _path.lineTo(5, 10) _path.closeSubpath() _path.moveTo(5, 13) _path.lineTo(23, 13) _path.lineTo(23, 15) _path.lineTo(5, 15) _path.closeSubpath() _path.moveTo(5, 18) _path.lineTo(23, 18) _path.lineTo(23, 20) _path.lineTo(5, 20) _path.closeSubpath()
def createSquareGrid(self, part_item, radius, bounds): """Instantiate an area of griditems arranged on a square lattice. Args: part_item (TYPE): Description radius (TYPE): Description bounds (TYPE): Description Returns: TYPE: Description """ doLattice = SquareDnaPart.latticeCoordToModelXY doPosition = SquareDnaPart.positionToLatticeCoordRound x_l, x_h, y_l, y_h = bounds x_l = x_l + SquareDnaPart.PAD_GRID_XL x_h = x_h + SquareDnaPart.PAD_GRID_XH y_h = y_h + SquareDnaPart.PAD_GRID_YL y_l = y_l + SquareDnaPart.PAD_GRID_YH 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, scale_factor=sf) row_h, col_h = doPosition(radius, x_h, -y_h, scale_factor=sf) redo_neighbors = (row_l, col_l, row_h, col_h) != \ self.previous_grid_bounds or self.previous_grid_type != self.grid_type self.previous_grid_type = self.grid_type if redo_neighbors: neighbor_map = dict() path = QPainterPath() is_pen_down = False draw_lines = self.draw_lines for row in range(row_l, row_h + 1): for column in range(col_l, col_h + 1): x, y = doLattice(radius, row, column, 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, coord=(row, column)) if self._draw_gridpoint_coordinates: font = QFont(styles.THE_FONT) path.addText(x - 10, -y + 5, font, "%s,%s" % (-row, column)) pt.setPen(getPenObj(styles.GRAY_STROKE, styles.EMPTY_HELIX_STROKE_WIDTH)) # if x == 0 and y == 0: # pt.setBrush(getBrushObj(Qt.gray)) points.append(pt) self.points_dict[(-row, column)] = pt if redo_neighbors: self.previous_grid_bounds = (row_l, col_l, row_h, col_h) is_pen_down = False # pen up # DO VERTICAL LINES if draw_lines: for column in range(col_l, col_h + 1): for row in range(row_l, row_h + 1): x, y = doLattice(radius, row, column, scale_factor=sf) if is_pen_down: path.lineTo(x, -y) else: is_pen_down = True path.moveTo(x, -y) is_pen_down = False # pen up self._path.setPath(path)
def paintEvent(self, pe): p = QPainter(self) p.setRenderHint(QPainter.Antialiasing) pen = QPen() pen.setWidth(1) pen.setColor(QColor(0x8c, 0xa3, 0xb0)) p.setPen(pen) p.setBrush(QColor(0xe4, 0xec, 0xf4)) rx = 6 space = self.space w = self.usable_width kw = self.key_w def drawRow(row, sx, sy, last_end=False): x = sx y = sy keys = row rw = w - sx i = 0 for k in keys: rect = QRectF(x, y, kw, kw) if i == len(keys) - 1 and last_end: rect.setWidth(rw) p.drawRoundedRect(rect, rx, rx) p.setPen(Qt.black) rect.adjust(5, 1, 0, 0) p.setFont(self.lowerFont) p.drawText( rect, Qt.AlignLeft | Qt.AlignBottom, self.regular_text(k)) p.setFont(self.upperFont) p.drawText( rect, Qt.AlignLeft | Qt.AlignTop, self.shift_text(k)) rw = rw - space - kw x = x + space + kw i = i + 1 p.setPen(pen) return (x, rw) x = .5 y = .5 keys = self.kb["keys"] ext_return = self.kb["extended_return"] first_key_w = 0 rows = 4 remaining_x = [0, 0, 0, 0] remaining_widths = [0, 0, 0, 0] for i in range(0, rows): if first_key_w > 0: first_key_w = first_key_w * 1.375 if self.kb == self.kb_105 and i == 3: first_key_w = kw * 1.275 rect = QRectF(x, y, first_key_w, kw) p.drawRoundedRect(rect, rx, rx) x = x + first_key_w + space else: first_key_w = kw x, rw = drawRow(keys[i], x, y, i == 1 and not ext_return) remaining_x[i] = x remaining_widths[i] = rw if i != 1 and i != 2: rect = QRectF(x, y, rw, kw) p.drawRoundedRect(rect, rx, rx) x = .5 y = y + space + kw if ext_return: rx = rx * 2 x1 = remaining_x[1] y1 = .5 + kw * 1 + space * 1 w1 = remaining_widths[1] x2 = remaining_x[2] y2 = .5 + kw * 2 + space * 2 # this is some serious crap... but it has to be so # maybe one day keyboards won't look like this... # one can only hope pp = QPainterPath() pp.moveTo(x1, y1 + rx) pp.arcTo(x1, y1, rx, rx, 180, -90) pp.lineTo(x1 + w1 - rx, y1) pp.arcTo(x1 + w1 - rx, y1, rx, rx, 90, -90) pp.lineTo(x1 + w1, y2 + kw - rx) pp.arcTo(x1 + w1 - rx, y2 + kw - rx, rx, rx, 0, -90) pp.lineTo(x2 + rx, y2 + kw) pp.arcTo(x2, y2 + kw - rx, rx, rx, -90, -90) pp.lineTo(x2, y1 + kw) pp.lineTo(x1 + rx, y1 + kw) pp.arcTo(x1, y1 + kw - rx, rx, rx, -90, -90) pp.closeSubpath() p.drawPath(pp) else: x = remaining_x[2] y = .5 + kw * 2 + space * 2 rect = QRectF(x, y, remaining_widths[2], kw) p.drawRoundedRect(rect, rx, rx) QWidget.paintEvent(self, pe)