def setWedgeGizmo(self, neighbor_virtual_helix: int, neighbor_virtual_helix_item: SliceVirtualHelixItemT): """Adds a :class:`WedgeGizmo` to oriented toward the specified neighbor vhi. Called by :meth:`SliceNucleicAcidPartItem._refreshVirtualHelixItemGizmos`, before :meth:`setWedgeGizmo` and :meth:`endAddWedgeGizmos`. Args: neighbor_virtual_helix: the id_num of neighboring virtual helix neighbor_virtual_helix_item: the neighboring virtual helix item """ wg_dict = self.wedge_gizmos nvhi = neighbor_virtual_helix_item pos = self.scenePos() line = QLineF(pos, nvhi.scenePos()) line.translate(_RADIUS, _RADIUS) if line.length() > (_RADIUS * 1.99): color = '#5a8bff' else: color = '#cc0000' line.setLength(_RADIUS) if neighbor_virtual_helix in wg_dict: wedge_item = wg_dict[neighbor_virtual_helix] else: wedge_item = WedgeGizmo(_RADIUS, WEDGE_RECT, self) wg_dict[neighbor_virtual_helix] = wedge_item wedge_item.showWedge(line.angle(), color, outline_only=False) self._added_wedge_gizmos.add(neighbor_virtual_helix)
def setWedgeGizmo(self, neighbor_virtual_helix, neighbor_virtual_helix_item): """Adds a WedgeGizmo to oriented toward the specified neighbor vhi. Called by NucleicAcidPartItem _refreshVirtualHelixItemGizmos, in between with beginAddWedgeGizmos and endAddWedgeGizmos. Args: neighbor_virtual_helix (int): the id_num of neighboring virtual helix neighbor_virtual_helix_item (cadnano.views.sliceview.virtualhelixitem.VirtualHelixItem): the neighboring virtual helix item """ wg_dict = self.wedge_gizmos nvhi = neighbor_virtual_helix_item pos = self.scenePos() line = QLineF(pos, nvhi.scenePos()) line.translate(_RADIUS, _RADIUS) if line.length() > (_RADIUS * 1.99): color = '#5a8bff' else: color = '#cc0000' line.setLength(_RADIUS) if neighbor_virtual_helix in wg_dict: wedge_item = wg_dict[neighbor_virtual_helix] else: wedge_item = WedgeGizmo(_RADIUS, WEDGE_RECT, self) wg_dict[neighbor_virtual_helix] = wedge_item wedge_item.showWedge(line.angle(), color, outline_only=False) self._added_wedge_gizmos.add(neighbor_virtual_helix)
def setWedgeGizmo(self, neighbor_virtual_helix: int, neighbor_virtual_helix_item: GridVirtualHelixItemT): """Adds a WedgeGizmo to oriented toward the specified neighbor vhi. Called by NucleicAcidPartItem _refreshVirtualHelixItemGizmos, in between with beginAddWedgeGizmos and endAddWedgeGizmos. Args: neighbor_virtual_helix: the id_num of neighboring virtual helix neighbor_virtual_helix_item: the neighboring virtual helix item """ wg_dict = self.wedge_gizmos nvhi = neighbor_virtual_helix_item nvhi_name = nvhi.getProperty('name') pos = self.scenePos() line = QLineF(pos, nvhi.scenePos()) line.translate(_RADIUS, _RADIUS) if line.length() > (_RADIUS*1.99): color = '#5a8bff' else: color = '#cc0000' nvhi_name = nvhi_name + '*' # mark as invalid line.setLength(_RADIUS) if neighbor_virtual_helix in wg_dict: wedge_item = wg_dict[neighbor_virtual_helix] else: wedge_item = WedgeGizmo(_RADIUS, WEDGE_RECT, self) wg_dict[neighbor_virtual_helix] = wedge_item wedge_item.showWedge(line.angle(), color, outline_only=False) self._added_wedge_gizmos.add(neighbor_virtual_helix)
def moveUIPoint(contour, point, delta): if point.segmentType is None: # point is an offCurve. Get its sibling onCurve and the other # offCurve. onCurve, otherPoint = _getOffCurveSiblingPoints(contour, point) # if the onCurve is selected, the offCurve will move along with it if onCurve.selected: return point.move(delta) if not onCurve.smooth: contour.dirty = True return # if the onCurve is smooth, we need to either... if otherPoint.segmentType is None and not otherPoint.selected: # keep the other offCurve inline line = QLineF(point.x, point.y, onCurve.x, onCurve.y) otherLine = QLineF( onCurve.x, onCurve.y, otherPoint.x, otherPoint.y) line.setLength(line.length() + otherLine.length()) otherPoint.x = line.x2() otherPoint.y = line.y2() else: # keep point in tangency with onCurve -> otherPoint segment, # ie. do an orthogonal projection line = QLineF(otherPoint.x, otherPoint.y, onCurve.x, onCurve.y) n = line.normalVector() n.translate(QPointF(point.x, point.y) - n.p1()) targetPoint = QPointF() n.intersect(line, targetPoint) # check that targetPoint is beyond its neighbor onCurve # we do this by calculating position of the offCurve and second # onCurve relative to the first onCurve. If there is no symmetry # in at least one of the axis, then we need to clamp onCurvePoint = line.p2() onDistance = line.p1() - onCurvePoint newDistance = targetPoint - onCurvePoint if (onDistance.x() >= 0) != (newDistance.x() <= 0) or \ (onDistance.y() >= 0) != (newDistance.y() <= 0): targetPoint = onCurvePoint # ok, now set pos point.x, point.y = targetPoint.x(), targetPoint.y() else: # point is an onCurve. Move its offCurves along with it. index = contour.index(point) point.move(delta) for d in (-1, 1): # edge-case: contour open, trailing offCurve and moving first # onCurve in contour if contour.open and index == 0 and d == -1: continue pt = contour.getPoint(index + d) if pt.segmentType is None: pt.move(delta) contour.dirty = True
def moveUIPoint(contour, point, delta): if point.segmentType is None: # point is an offCurve. Get its sibling onCurve and the other # offCurve. onCurve, otherPoint = _getOffCurveSiblingPoints(contour, point) # if the onCurve is selected, the offCurve will move along with it if onCurve.selected: return point.move(delta) if not onCurve.smooth: contour.dirty = True return # if the onCurve is smooth, we need to either... if otherPoint.segmentType is None and not otherPoint.selected: # keep the other offCurve inline line = QLineF(point.x, point.y, onCurve.x, onCurve.y) otherLine = QLineF(onCurve.x, onCurve.y, otherPoint.x, otherPoint.y) line.setLength(line.length() + otherLine.length()) otherPoint.x = line.x2() otherPoint.y = line.y2() else: # keep point in tangency with onCurve -> otherPoint segment, # ie. do an orthogonal projection line = QLineF(otherPoint.x, otherPoint.y, onCurve.x, onCurve.y) n = line.normalVector() n.translate(QPointF(point.x, point.y) - n.p1()) targetPoint = QPointF() n.intersect(line, targetPoint) # check that targetPoint is beyond its neighbor onCurve # we do this by calculating position of the offCurve and second # onCurve relative to the first onCurve. If there is no symmetry # in at least one of the axis, then we need to clamp onCurvePoint = line.p2() onDistance = line.p1() - onCurvePoint newDistance = targetPoint - onCurvePoint if (onDistance.x() >= 0) != (newDistance.x() <= 0) or \ (onDistance.y() >= 0) != (newDistance.y() <= 0): targetPoint = onCurvePoint # ok, now set pos point.x, point.y = targetPoint.x(), targetPoint.y() else: # point is an onCurve. Move its offCurves along with it. index = contour.index(point) point.move(delta) for d in (-1, 1): # edge-case: contour open, trailing offCurve and moving first # onCurve in contour if contour.open and index == 0 and d == -1: continue pt = contour.getPoint(index + d) if pt.segmentType is None: pt.move(delta) contour.dirty = True
def _draw_arrow(self, event, painter): if self.info["mouth_is_opened"][0] == False or self.prediction == 4: return angles = [135, 90, 45, 180, None, 0, 225, 270, 0] angleline = QLineF() angleline.setP1(QPointF(*_mouse_controller.position)) angleline.setAngle(angles[self.prediction]) angleline.setLength(100) painter.setPen(QPen(Qt.red, 5, Qt.SolidLine)) painter.drawLine(angleline)
def rotateUIPointAroundRefLine(x1, y1, x2, y2, pt): """ Given three points p1, p2, pt this rotates pt around p2 such that p1,p2 and p1,pt are collinear. """ line = QLineF(pt.x, pt.y, x2, y2) p2p_l = line.length() line.setP1(QPointF(x1, y1)) p1p2_l = line.length() if not p1p2_l: return line.setLength(p1p2_l + p2p_l) pt.x = line.x2() pt.y = line.y2()
class MyArrow(QGraphicsLineItem): def __init__(self, scene, Source, Dest): super(MyArrow, self).__init__() #设置起点x,y Source_x = Source[0] Source_y = Source[1] #设置终点x,y Dest_x = Dest[0] Dest_y = Dest[1] #绘制连线 self.source = QPointF(Source_x, Source_y) self.dest = QPointF(Dest_x, Dest_y) self.line = QLineF(self.source, self.dest) self.line.setLength(self.line.length() - 20) scene.addItem(self) def prepareGeometryChange(self): self.update() def paint(self, QPainter, QStyleOptionGraphicsItem, QWidget_widget=None): # setPen pen = QPen() pen.setWidth(2) pen.setJoinStyle(Qt.MiterJoin) QPainter.setPen(pen) # setBrush brush = QBrush() brush.setColor(Qt.black) brush.setStyle(Qt.SolidPattern) QPainter.setBrush(brush) #绘制终点箭头 v = self.line.unitVector() v.setLength(10) v.translate(QPointF(self.line.dx(), self.line.dy())) n = v.normalVector() n.setLength(n.length() * 0.5) n2 = n.normalVector().normalVector() p1 = v.p2() p2 = n.p2() p3 = n2.p2() QPainter.drawLine(self.line) QPainter.drawPolygon(p1, p2, p3)
def moveUIPoint(contour, point, delta): if point.segmentType is None: # point is an offCurve. Get its sibling onCurve and the other # offCurve. siblings = _getOffCurveSiblingPoints(contour, point) # if an onCurve is selected, the offCurve will move along with it if not siblings: return point.move(delta) for onCurve, otherPoint in siblings: if not onCurve.smooth: continue # if the onCurve is smooth, we need to either... if otherPoint.segmentType is None and not otherPoint.selected: # keep the other offCurve inline line = QLineF(point.x, point.y, onCurve.x, onCurve.y) otherLine = QLineF( onCurve.x, onCurve.y, otherPoint.x, otherPoint.y) line.setLength(line.length() + otherLine.length()) otherPoint.x = line.x2() otherPoint.y = line.y2() else: # keep point in tangency with onCurve -> otherPoint segment, # i.e. do an orthogonal projection point.x, point.y, _ = bezierMath.lineProjection( onCurve.x, onCurve.y, otherPoint.x, otherPoint.y, point.x, point.y, False) else: # point is an onCurve. Move its offCurves along with it. index = contour.index(point) point.move(delta) for d in (-1, 1): # edge-case: contour open, trailing offCurve and moving first # onCurve in contour if contour.open and index == 0 and d == -1: continue pt = contour.getPoint(index + d) if pt.segmentType is None: # avoid double move for qCurve with single offCurve if d > 0: otherPt = contour.getPoint(index + 2 * d) if otherPt.segmentType is not None and \ otherPt.segmentType != "move" and otherPt.selected: continue pt.move(delta) maybeProjectUISmoothPointOffcurve(contour, point) contour.dirty = True
def ulti(self): scene_items = self.scene().items() for i in scene_items: if (isinstance(i, Minion) or isinstance(i, BigMinion)) and i.team != self.team: this_line = QLineF(self.pos(), i.pos()) if this_line.length() <= 150: this_line.setLength(150) i.setPos(i.x() + this_line.dx(), i.y() + this_line.dy()) elif (i.__class__.__name__ == 'Tower' or i.__class__.__name__ == 'Nexus' or i.__class__.__name__ == 'Inhibitor') and i.team != self.team: this_line = QLineF(self.pos(), i.pos()) if this_line.length() <= 150: i.decrease_health(100) self.ulti_available = False self.ulti_cooldown_timer.start(self.cooldown)
def arrow_path_concave(line, width): """ Return a :class:`QPainterPath` of a pretty looking arrow. """ path = QPainterPath() p1, p2 = line.p1(), line.p2() if p1 == p2: return path baseline = QLineF(line) # Require some minimum length. baseline.setLength(max(line.length() - width * 3, width * 3)) start, end = baseline.p1(), baseline.p2() mid = (start + end) / 2.0 normal = QLineF.fromPolar(1.0, baseline.angle() + 90).p2() path.moveTo(start) path.lineTo(start + (normal * width / 4.0)) path.quadTo(mid + (normal * width / 4.0), end + (normal * width / 1.5)) path.lineTo(end - (normal * width / 1.5)) path.quadTo(mid - (normal * width / 4.0), start - (normal * width / 4.0)) path.closeSubpath() arrow_head_len = width * 4 arrow_head_angle = 50 line_angle = line.angle() - 180 angle_1 = line_angle - arrow_head_angle / 2.0 angle_2 = line_angle + arrow_head_angle / 2.0 points = [ p2, p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(), baseline.p2(), p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(), p2 ] poly = QPolygonF(points) path_head = QPainterPath() path_head.addPolygon(poly) path = path.united(path_head) return path
def drawWidget(self, qp): c = self.rect().center() c_coords = c.x(), c.y() background_color = self.palette().color(QPalette.Background) # paint inner trackpad qp.setPen(QPen(self.fishbowl_color, self.fishbowl_border_size, Qt.SolidLine)) # draw fishbowl qp.setBrush(QBrush(Qt.gray, Qt.SolidPattern)) qp.drawEllipse(c, *([self.fishbowl_size] * 2)) # draw axis lines qp.setPen(QPen(self.fishbowl_color, self.fishbowl_thin_border_size, Qt.DashDotDotLine)) for angle in range(0, 420, 45): line = QLineF(); line.setP1(c); line.setAngle(angle); line.setLength(self.fishbowl_size) qp.drawLine(line) # draw wheel separators line = QLineF(); line.setP1(c + QPoint(self.wheel_size, 0)); line.setAngle(0); line.setLength(self.wheel_width) qp.drawLine(line) line = QLineF(); line.setP1(c + QPoint(0, -self.wheel_size)); line.setAngle(90); line.setLength(self.wheel_width) qp.drawLine(line) line = QLineF(); line.setP1(c + QPoint(-self.wheel_size, 0)); line.setAngle(180); line.setLength(self.wheel_width) qp.drawLine(line) line = QLineF(); line.setP1(c + QPoint(0, self.wheel_size)); line.setAngle(270); line.setLength(self.wheel_width) qp.drawLine(line) qp.setPen(QPen(self.fishbowl_color, self.fishbowl_border_size, Qt.SolidLine)) # draw dead enemies for i, enemy in enumerate([x for x in self.enemies if x.dead]): qp.setBrush(QBrush(enemy.color, Qt.SolidPattern)) qp.drawEllipse(c + QPoint(*self.scale_point(enemy.coords)), *([self.npc_size] * 2)) # draw alive enemies for i, enemy in enumerate([x for x in self.enemies if not x.dead]): qp.setBrush(QBrush(enemy.color, Qt.SolidPattern)) qp.drawEllipse(c + QPoint(*self.scale_point(enemy.coords)), *([self.npc_size] * 2)) # draw player qp.setBrush(QBrush(self.player.color, Qt.SolidPattern)) qp.drawEllipse(c + QPoint(*self.scale_point(self.player.coords)), *([self.npc_size] * 2))
def __init__(self, position, angle, arrow_size, value, unit): super(StressRepresentation, self).__init__() arrow_line = QLineF() arrow_line.setP1(position) arrow_line.setLength(arrow_size) arrow_line.setAngle(angle) arrow = QGraphicsLineItem() arrow.setLine(arrow_line) self.addToGroup(arrow) arrow_head1_line = QLineF() arrow_head1_line.setP1(arrow_line.p1()) arrow_head1_line.setLength(arrow_size / 4) arrow_head1_line.setAngle(arrow_line.angle() + 45) arrow_head1 = QGraphicsLineItem() arrow_head1.setLine(arrow_head1_line) self.addToGroup(arrow_head1) arrow_head2_line = QLineF() arrow_head2_line.setP1(arrow_line.p1()) arrow_head2_line.setLength(arrow_size / 4) arrow_head2_line.setAngle(arrow_line.angle() - 45) arrow_head2 = QGraphicsLineItem() arrow_head2.setLine(arrow_head2_line) self.addToGroup(arrow_head2) text = QGraphicsTextItem() text.setPlainText(f'{str(value)}{unit}') text.setPos(arrow_line.p2()) self.addToGroup(text) self._set_color()
def move_forward(self): # move object if self.should_be_moving: ln = QLineF(self.pos(), self.destination) ln.setLength(self.speed) self.rotate_to_point(self.destination) # avoid collision colliding_items = self.collidingItems() for i in colliding_items: if isinstance(i, StaticGameObject): collision_line = QLineF(self.pos(), i.pos()) collision_line.setLength(30) self.setPos(self.x() - collision_line.dx(), self.y() - collision_line.dy()) # move object forward at current angle self.setPos(self.x() + ln.dx(), self.y() + ln.dy()) self.x_prev = self.pos().x() self.y_prev = self.pos().y()
def move_forward(self): '''Overwriting move forward so it does not evade obstacles ''' # move object if self.has_target: return if self.should_be_moving: ln = QLineF(self.pos(), self.destination) ln.setLength(self.speed) self.rotate_to_point(self.destination) # avoid collision colliding_items = self.collidingItems() for i in colliding_items: if isinstance(i, StaticGameObject): return # move object forward at current angle self.setPos(self.x() + ln.dx(), self.y() + ln.dy()) self.x_prev = self.pos().x() self.y_prev = self.pos().y()
def arrow_path_plain(line, width): """ Return an :class:`QPainterPath` of a plain looking arrow. """ path = QPainterPath() p1, p2 = line.p1(), line.p2() if p1 == p2: return path baseline = QLineF(line) # Require some minimum length. baseline.setLength(max(line.length() - width * 3, width * 3)) path.moveTo(baseline.p1()) path.lineTo(baseline.p2()) stroker = QPainterPathStroker() stroker.setWidth(width) path = stroker.createStroke(path) arrow_head_len = width * 4 arrow_head_angle = 50 line_angle = line.angle() - 180 angle_1 = line_angle - arrow_head_angle / 2.0 angle_2 = line_angle + arrow_head_angle / 2.0 points = [ p2, p2 + QLineF.fromPolar(arrow_head_len, angle_1).p2(), p2 + QLineF.fromPolar(arrow_head_len, angle_2).p2(), p2 ] poly = QPolygonF(points) path_head = QPainterPath() path_head.addPolygon(poly) path = path.united(path_head) return path
def showWedge(self, angle, color, extended=False, rev_gradient=False, outline_only=False): """Summary Args: angle (TYPE): Description color (TYPE): Description extended (bool, optional): Description rev_gradient (bool, optional): Description outline_only (bool, optional): Description """ # Hack to keep wedge in front # self.setRotation(self.pre_xover_item_group.rotation()) self._last_params = (angle, color, extended, rev_gradient, outline_only) radius = self._radius span = self.pre_xover_item_group.partCrossoverSpanAngle() / 2 radius_adjusted = radius + (_WEDGE_RECT_GAIN / 2) tip = QPointF(radius_adjusted, radius_adjusted) EXT = 1.35 if extended else 1.0 # print("wtf", tip, pos) base_p2 = QPointF(1, 1) line0 = QLineF(tip, QPointF(base_p2)) line1 = QLineF(tip, QPointF(base_p2)) line2 = QLineF(tip, QPointF(base_p2)) quad_scale = 1 + (.22 * (span - 5) / 55) # lo+(hi-lo)*(val-min)/(max-min) line0.setLength(radius_adjusted * EXT * quad_scale) # for quadTo control point line1.setLength(radius_adjusted * EXT) line2.setLength(radius_adjusted * EXT) line0.setAngle(angle) line1.setAngle(angle - span) line2.setAngle(angle + span) path = QPainterPath() if outline_only: self.setPen(getPenObj(color, 0.5, alpha=128, capstyle=Qt.RoundCap)) path.moveTo(line1.p2()) path.quadTo(line0.p2(), line2.p2()) else: gradient = QRadialGradient(tip, radius_adjusted * EXT) color1 = getColorObj(color, alpha=80) color2 = getColorObj(color, alpha=0) if rev_gradient: color1, color2 = color2, color1 if extended: gradient.setColorAt(0, color1) gradient.setColorAt(radius_adjusted / (radius_adjusted * EXT), color1) gradient.setColorAt( radius_adjusted / (radius_adjusted * EXT) + 0.01, color2) gradient.setColorAt(1, color2) else: gradient.setColorAt(0, getColorObj(color, alpha=50)) brush = QBrush(gradient) self.setBrush(brush) path.moveTo(line1.p1()) path.lineTo(line1.p2()) path.quadTo(line0.p2(), line2.p2()) path.lineTo(line2.p1()) self.setPath(path) self.show()
def _drawGuidelines(painter, glyph, scale, rect, guidelines, drawLines=True, drawText=True, drawSelection=True, color=None): if not (drawLines or drawText): return xMin, yMin, width, height = rect xMax = xMin + width yMax = yMin + height for line in guidelines: color_ = color if color_ is None: if line.color: color_ = colorToQColor(line.color) else: color_ = defaultColor("glyphGuideline") painter.save() painter.setPen(color) line1 = None if None not in (line.x, line.y): if line.angle is not None: # make an infinite line that intersects *(line.x, line.y)* # 1. make horizontal line from *(line.x, line.y)* of length # *diagonal* diagonal = math.sqrt(width**2 + height**2) line1 = QLineF(line.x, line.y, line.x + diagonal, line.y) # 2. set the angle # defcon guidelines are clockwise line1.setAngle(line.angle) # 3. reverse the line and set length to 2 * *diagonal* line1.setPoints(line1.p2(), line1.p1()) line1.setLength(2 * diagonal) else: line1 = QLineF(xMin, line.y, xMax, line.y) textX = 0 textY = 0 if drawLines: if line1 is not None: # line drawLine(painter, line1.x1(), line1.y1(), line1.x2(), line1.y2()) # point x, y = line.x, line.y smoothWidth = 8 * scale smoothHalf = smoothWidth / 2.0 painter.save() pointPath = QPainterPath() x -= smoothHalf y -= smoothHalf pointPath.addEllipse(x, y, smoothWidth, smoothWidth) pen = QPen(color_) pen.setWidthF(1 * scale) painter.setPen(pen) if drawSelection and line.selected: painter.fillPath(pointPath, color_) painter.drawPath(pointPath) painter.restore() else: if line.y is not None: drawLine(painter, xMin, line.y, xMax, line.y) elif line.x is not None: drawLine(painter, line.x, yMin, line.x, yMax) if drawText and line.name: if line1 is not None: textX = line.x textY = line.y - 6 * scale xAlign = "center" else: if line.y is not None: fontSize = painter.font().pointSize() textX = glyph.width + 6 * scale textY = line.y - (fontSize / 3.5) * scale elif line.x is not None: textX = line.x + 6 * scale textY = 0 xAlign = "left" drawTextAtPoint(painter, line.name, textX, textY, scale, xAlign=xAlign) painter.restore()
def _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()
class LineItem(QGraphicsLineItem): def __init__(self, boxName, fromBox, toBox, position, scene, parentForm, style=Qt.SolidLine, rect=None, matrix=QTransform()): super(LineItem, self).__init__() self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsFocusable) self.style = style self.boxName = boxName self._fromBox = None self._toBox = None if fromBox == None: x1 = 10 y1 = 10 else: x1 = fromBox.boundingRect().right() y1 = fromBox.boundingRect().top( ) + fromBox.boundingRect().height() * 0.3 if toBox == None: x2 = 100 y2 = 100 else: x2 = toBox.boundingRect().left() y2 = toBox.boundingRect().top( ) + fromBox.boundingRect().height() * 0.3 self.parentForm = parentForm self.source = QPointF(x1, y1) self.dest = QPointF(x2, y2) self.fromBox = fromBox self.toBox = toBox self.direction = "a" self.myColor = Qt.black self.setPen( QPen(self.myColor, 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.line = QLineF(self.source, self.dest) self.line.setLength(self.line.length() - 5) self.resetLine() self.scene = scene scene.clearSelection() scene.addItem(self) self.setSelected(True) self.setFocus() global Dirty Dirty = True def resetLine(self): if self.fromBox == None and self.toBox == None: return if self.fromBox == None: x2 = self.toBox.x() y2 = self.toBox.y() + self.toBox.boundingRect().height() * 0.3 x1 = x2 - 30 y1 = y2 elif self.toBox == None: x1 = self.fromBox.x() + self.fromBox.boundingRect().width() y1 = self.fromBox.y() + self.fromBox.boundingRect().height() * 0.3 x2 = x1 + 30 y2 = y1 else: x_diff = self.toBox.x() - self.fromBox.x() y_diff = self.toBox.y() - self.fromBox.y() x_diff_standand = (self.fromBox.boundingRect().width() + self.toBox.boundingRect().width()) / 2 y_diff_standand = (self.fromBox.boundingRect().height() + self.toBox.boundingRect().height()) / 2 if ((abs(y_diff) < y_diff_standand)): if x_diff > 0: self.direction = "x>" x1 = self.fromBox.x() + self.fromBox.boundingRect().width() y1 = self.fromBox.y( ) + self.fromBox.boundingRect().height() * 0.3 x2 = self.toBox.x() y2 = self.toBox.y( ) + self.toBox.boundingRect().height() * 0.3 else: self.direction = "x<" x1 = self.fromBox.x() y1 = self.fromBox.y( ) + self.fromBox.boundingRect().height() * 0.67 x2 = self.toBox.x() + self.toBox.boundingRect().width() y2 = self.toBox.y( ) + self.toBox.boundingRect().height() * 0.67 elif ((abs(x_diff) < x_diff_standand)): if (y_diff > 0): self.direction = "y>" x1 = self.fromBox.x( ) + self.fromBox.boundingRect().width() * 0.3 y1 = self.fromBox.y() + self.fromBox.boundingRect().height( ) x2 = self.toBox.x( ) + self.toBox.boundingRect().width() * 0.3 y2 = self.toBox.y() else: self.direction = "y<" x1 = self.fromBox.x( ) + self.fromBox.boundingRect().width() * 0.67 y1 = self.fromBox.y() x2 = self.toBox.x( ) + self.toBox.boundingRect().width() * 0.67 y2 = self.toBox.y() + self.toBox.boundingRect().height() else: if (x_diff > 0) and (y_diff > 0): self.direction = "xy>" x1 = self.fromBox.x() + self.fromBox.boundingRect().width() y1 = self.fromBox.y( ) + self.fromBox.boundingRect().height() * 0.87 x2 = self.toBox.x( ) + self.toBox.boundingRect().width() * 0.13 y2 = self.toBox.y() elif ((x_diff < 0) and (y_diff < 0)): self.direction = "xy<" x1 = self.fromBox.x() y1 = self.fromBox.y( ) + self.fromBox.boundingRect().height() * 0.13 x2 = self.toBox.x( ) + self.toBox.boundingRect().width() * 0.87 y2 = self.toBox.y() + self.toBox.boundingRect().height() elif (x_diff > 0) and (y_diff < 0): self.direction = "x>y<" x1 = self.fromBox.x( ) + self.fromBox.boundingRect().width() * 0.87 y1 = self.fromBox.y() x2 = self.toBox.x() y2 = self.toBox.y( ) + self.toBox.boundingRect().height() * 0.87 else: self.direction = "x<y>" x1 = self.fromBox.x( ) + self.fromBox.boundingRect().width() * 0.13 y1 = self.fromBox.y() + self.fromBox.boundingRect().height( ) x2 = self.toBox.x() + self.toBox.boundingRect().width() y2 = self.toBox.y( ) + self.toBox.boundingRect().height() * 0.13 self.source = QPointF(x1, y1) self.dest = QPointF(x2, y2) self.line = QLineF(self.source, self.dest) self.line.setLength(self.line.length() - 5) @property def boxName(self): return self._boxName @boxName.setter def boxName(self, value): if not isinstance(value, str): raise ValueError('boxName must be an string!') self._boxName = value def toSaveJson(self): data = { "type": "Line", "boxName": self.boxName, "strFromBox": self.fromBox.boxName, "strToBox": self.toBox.boxName, "style": self.style, "rotation": self.rotation() } return data @property def fromBox(self): return self._fromBox @fromBox.setter def fromBox(self, value): if value != None: if not isinstance(value, QGraphicsTextItem): raise ValueError('boxName must be an string!') self._fromBox = value self.resetLine() @property def toBox(self): return self._toBox @toBox.setter def toBox(self, value): if value != None: if not isinstance(value, QGraphicsTextItem): raise ValueError('boxName must be an string!') self._toBox = value self.resetLine() def parentWidget(self): return self.scene().views()[0] def itemChange(self, change, variant): if change != QGraphicsItem.ItemSelectedChange: global Dirty Dirty = True return QGraphicsLineItem.itemChange(self, change, variant) def mouseDoubleClickEvent(self, event): dialog = LineItemDlg(self, self.parentWidget(), self.parentWidget(), self.scene, self.parentForm) dialog.exec_() def paint(self, QPainter, QStyleOptionGraphicsItem, QWidget_widget=None): # setPen pen = QPen() pen.setWidth(1) pen.setJoinStyle(Qt.MiterJoin) #让箭头变尖 QPainter.setPen(pen) # draw line QPainter.drawLine(self.line) ptextx = (self.line.x1() + self.line.x2()) / 2 ptexty = (self.line.y1() + self.line.y2()) / 2 ptexty -= 5 ptextx -= len(self.boxName) * 3 QPainter.drawText(QPointF(ptextx, ptexty), self.boxName) #Painter.drawText(QPointF(ptextx, ptexty+20), self.direction) # setBrush brush = QBrush() brush.setColor(Qt.black) brush.setStyle(Qt.SolidPattern) QPainter.setBrush(brush) v = self.line.unitVector() v.setLength(5) v.translate(QPointF(self.line.dx(), self.line.dy())) n = v.normalVector() n.setLength(n.length() * 0.5) n2 = n.normalVector().normalVector() p1 = v.p2() p2 = n.p2() p3 = n2.p2() # 方法1 QPainter.drawLine(self.line) QPainter.drawPolygon(p1, p2, p3) QPainter.drawArc(10, 10, 50, 50, 0, 180 * 16) v = self.line.unitVector() v.setLength(5) v.translate(QPointF(10, 60)) n = v.normalVector() n.setLength(n.length() * 0.5) n2 = n.normalVector().normalVector() p1 = v.p2() p2 = n.p2() p3 = n2.p2() # 方法1 #QPainter.drawLine(self.line) QPainter.drawPolygon(p1, p2, p3) self.scene.update()
def showWedge(self, angle, color, extended=False, rev_gradient=False, outline_only=False): """Summary Args: angle (TYPE): Description color (TYPE): Description extended (bool, optional): Description rev_gradient (bool, optional): Description outline_only (bool, optional): Description """ # Hack to keep wedge in front # self.setRotation(self.pre_xover_item_group.rotation()) self._last_params = (angle, color, extended, rev_gradient, outline_only) radius = self._radius span = self.pre_xover_item_group.partCrossoverSpanAngle() / 2 radius_adjusted = radius + (_WEDGE_RECT_GAIN / 2) tip = QPointF(radius_adjusted, radius_adjusted) EXT = 1.35 if extended else 1.0 # print("wtf", tip, pos) base_p2 = QPointF(1, 1) line0 = QLineF(tip, QPointF(base_p2)) line1 = QLineF(tip, QPointF(base_p2)) line2 = QLineF(tip, QPointF(base_p2)) quad_scale = 1 + (.22*(span - 5) / 55) # lo+(hi-lo)*(val-min)/(max-min) line0.setLength(radius_adjusted * EXT*quad_scale) # for quadTo control point line1.setLength(radius_adjusted * EXT) line2.setLength(radius_adjusted * EXT) line0.setAngle(angle) line1.setAngle(angle - span) line2.setAngle(angle + span) path = QPainterPath() if outline_only: self.setPen(getPenObj(color, 0.5, alpha=128, capstyle=Qt.RoundCap)) path.moveTo(line1.p2()) path.quadTo(line0.p2(), line2.p2()) else: gradient = QRadialGradient(tip, radius_adjusted * EXT) color1 = getColorObj(color, alpha=80) color2 = getColorObj(color, alpha=0) if rev_gradient: color1, color2 = color2, color1 if extended: gradient.setColorAt(0, color1) gradient.setColorAt(radius_adjusted / (radius_adjusted * EXT), color1) gradient.setColorAt(radius_adjusted / (radius_adjusted * EXT) + 0.01, color2) gradient.setColorAt(1, color2) else: gradient.setColorAt(0, getColorObj(color, alpha=50)) brush = QBrush(gradient) self.setBrush(brush) path.moveTo(line1.p1()) path.lineTo(line1.p2()) path.quadTo(line0.p2(), line2.p2()) path.lineTo(line2.p1()) self.setPath(path) self.show()
class EdgeItem(QGraphicsLineItem): def __init__(self, boxName, fromLocation, toLocation, guard, reset, scene, parentForm, style=Qt.SolidLine, rect=None, matrix=QTransform()): super(EdgeItem, self).__init__() self.setFlags(QGraphicsItem.ItemIsSelectable | QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsFocusable) self.style = style self.boxName = boxName self.guard = guard self.reset = reset self._fromLocation = None self._toLocation = None if fromLocation == None: x1 = 10 y1 = 10 else: x1 = fromLocation.rect.right() y1 = fromLocation.rect.top() + fromLocation.rect.height() * 0.3 if toLocation == None: x2 = 100 y2 = 100 else: x2 = toLocation.rect.left() y2 = toLocation.rect.top() + fromLocation.rect.height() * 0.3 self.parentForm = parentForm self.source = QPointF(x1, y1) self.dest = QPointF(x2, y2) self.fromLocation = fromLocation self.toLocation = toLocation self.direction = "a" self.myColor = Qt.black self.setPen( QPen(self.myColor, 2, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) self.line = QLineF(self.source, self.dest) self.line.setLength(self.line.length() - 5) self.resetLine() self.scene = scene scene.clearSelection() scene.addItem(self) self.setSelected(True) self.setFocus() global Dirty Dirty = True def drawLine2Self(self): haveEdges = [ strDirection for strDirection in self.fromLocation.edges.values() ] self.arcx1 = self.fromLocation.x() + self.fromLocation.rect.x( ) - 40 #-30 self.arcy1 = self.fromLocation.y() + self.fromLocation.rect.y( ) # -50#+self.fromLocation.rect.height*0.3 self.minAngle = 90 x1 = self.arcx1 + 33 y1 = self.arcy1 + 80 x2 = self.arcx1 + 40 y2 = self.arcy1 + 80 self.arcTextx = self.arcx1 self.arcTexty = self.arcy1 + 40 self.spanAngle = 180 if "top" not in haveEdges and self.fromLocation.isNameAbove == False: self.arcx1 = self.fromLocation.x() + self.fromLocation.rect.x( ) + 10 self.arcy1 = self.fromLocation.y() + self.fromLocation.rect.y( ) - 40 x1 = self.arcx1 + 80 y1 = self.arcy1 + 40 - 7 x2 = self.arcx1 + 80 y2 = self.arcy1 + 40 self.minAngle = 0 self.arcTextx = self.arcx1 + 40 self.arcTexty = self.arcy1 elif "left" not in haveEdges: self.arcx1 = self.fromLocation.x() + self.fromLocation.rect.x( ) - 40 #-30 self.arcy1 = self.fromLocation.y() + self.fromLocation.rect.y( ) + 10 # -50#+self.fromLocation.rect.height*0.3 self.minAngle = 90 x1 = self.arcx1 + 33 y1 = self.arcy1 + 80 x2 = self.arcx1 + 40 y2 = self.arcy1 + 80 self.arcTextx = self.arcx1 self.arcTexty = self.arcy1 + 40 elif "bottom" not in haveEdges and self.fromLocation.isNameAbove: self.arcx1 = self.fromLocation.x() + self.fromLocation.rect.x( ) + 10 self.arcy1 = self.fromLocation.y() + self.fromLocation.rect.y( ) + self.fromLocation.rect.height() - 40 self.minAngle = 180 x1 = self.arcx1 + 80 y1 = self.arcy1 + 7 + 40 x2 = self.arcx1 + 80 y2 = self.arcy1 + 40 self.arcTextx = self.arcx1 + 40 self.arcTexty = self.arcy1 + 80 elif "right" not in haveEdges: self.arcx1 = self.fromLocation.x() + self.fromLocation.rect.x( ) + self.fromLocation.rect.width() - 40 #-30 self.arcy1 = self.fromLocation.y() + self.fromLocation.rect.y( ) + 10 # -50#+self.fromLocation.rect.height*0.3 self.minAngle = 270 x1 = self.arcx1 + 7 + 25 + adjustX1 y1 = self.arcy1 + 80 x2 = self.arcx1 + 25 + adjustX1 y2 = self.arcy1 + 80 self.arcTextx = self.arcx1 + 80 self.arcTexty = self.arcy1 + 40 self.source = QPointF(x1, y1) self.dest = QPointF(x2, y2) self.line = QLineF(self.source, self.dest) self.line.setLength(self.line.length() - 5) #if 'time' not in listOfStrings : # print("Yes, 'time' NOT found in List : " , listOfStrings) def getQPixmap4Guard(self): guardFig = Figure(figsize=(5, 0.4)) canvas = FigureCanvas(guardFig) strData = self.guard try: guardFig.text(0.1, 0.3, strData, family="Consolas", fontsize=10) except: pass canvas.draw() size = canvas.size() width, height = size.width(), size.height() im = QImage(canvas.buffer_rgba(), width, height, QImage.Format_ARGB32) return QPixmap(im) def getQPixmap4Reset(self): guardFig = Figure(figsize=(5, 0.4)) canvas = FigureCanvas(guardFig) strData = self.reset try: guardFig.text(0.1, 0.3, strData, family="Consolas", fontsize=10) except: pass canvas.draw() size = canvas.size() width, height = size.width(), size.height() im = QImage(canvas.buffer_rgba(), width, height, QImage.Format_ARGB32) return QPixmap(im) def resetLine(self): self.direction = "" if self.fromLocation == None and self.toLocation == None: return if self.fromLocation == None: #self.toLocation.edges[self.boxName]="left" x2 = self.toLocation.x() + self.toLocation.rect.x() y2 = self.toLocation.y() + self.toLocation.rect.x( ) + self.toLocation.rect.height() * 0.3 x1 = x2 - 30 y1 = y2 elif self.toLocation == None: #self.fromLocation.edges[self.boxName]="right" x1 = self.fromLocation.x() + self.fromLocation.rect.x( ) + self.fromLocation.rect.width() y1 = self.fromLocation.y() + self.fromLocation.rect.y( ) + self.fromLocation.rect.height() * 0.3 x2 = x1 + 30 y2 = y1 else: adjustX1 = self.fromLocation.x() + self.fromLocation.rect.x() adjustX2 = self.toLocation.x() + self.toLocation.rect.x() adjustY1 = self.fromLocation.y() + self.fromLocation.rect.y() adjustY2 = self.toLocation.y() + self.toLocation.rect.y() if self.fromLocation.boxName == self.toLocation.boxName: self.drawLine2Self() self.fromLocation.edgeToSelf = self.boxName return x_diff = self.toLocation.x() - self.fromLocation.x() y_diff = self.toLocation.y() - self.fromLocation.y() x_diff_standand = (self.fromLocation.rect.width() + self.toLocation.rect.width()) / 2 y_diff_standand = (self.fromLocation.rect.height() + self.toLocation.rect.height()) / 2 if ((abs(y_diff) < y_diff_standand)): if x_diff > 0: self.direction = "x>" self.fromLocation.edges[self.boxName] = "right" self.toLocation.edges[self.boxName] = "left" x1 = self.fromLocation.rect.width() + adjustX1 y1 = self.fromLocation.rect.height() * 0.4 + adjustY1 x2 = adjustX2 y2 = self.toLocation.rect.height() * 0.4 + adjustY2 else: self.direction = "x<" self.fromLocation.edges[self.boxName] = "left" self.toLocation.edges[self.boxName] = "right" x1 = adjustX1 y1 = self.fromLocation.rect.height() * 0.6 + adjustY1 x2 = self.toLocation.rect.width() + adjustX2 y2 = self.toLocation.rect.height() * 0.6 + adjustY2 elif ((abs(x_diff) < x_diff_standand)): if (y_diff > 0): self.direction = "y>" self.fromLocation.edges[self.boxName] = "bottom" self.toLocation.edges[self.boxName] = "top" x1 = self.fromLocation.rect.width() * 0.4 + adjustX1 y1 = self.fromLocation.rect.height() + adjustY1 x2 = self.toLocation.rect.width() * 0.4 + adjustX2 y2 = adjustY2 else: self.direction = "y<" self.fromLocation.edges[self.boxName] = "top" self.toLocation.edges[self.boxName] = "bottom" x1 = self.fromLocation.rect.width() * 0.6 + adjustX1 y1 = adjustY1 x2 = self.toLocation.rect.width() * 0.6 + adjustX2 y2 = self.toLocation.rect.height() + adjustY2 else: if (x_diff > 0) and (y_diff > 0): self.direction = "xy>" self.fromLocation.edges[self.boxName] = "right" self.toLocation.edges[self.boxName] = "top" x1 = self.fromLocation.rect.width() + adjustX1 y1 = self.fromLocation.rect.height() * 0.8 + adjustY1 x2 = self.toLocation.rect.width() * 0.2 + adjustX2 y2 = adjustY2 elif ((x_diff < 0) and (y_diff < 0)): self.direction = "xy<" self.fromLocation.edges[self.boxName] = "left" self.toLocation.edges[self.boxName] = "bottom" x1 = adjustX1 y1 = self.fromLocation.rect.height() * 0.2 + adjustY1 x2 = self.toLocation.rect.width() * 0.8 + adjustX2 y2 = self.toLocation.rect.height() + adjustY2 elif (x_diff > 0) and (y_diff < 0): self.direction = "x>y<" self.fromLocation.edges[self.boxName] = "top" self.toLocation.edges[self.boxName] = "left" x1 = self.fromLocation.rect.width() * 0.8 + adjustX1 y1 = adjustY1 x2 = adjustX2 y2 = self.toLocation.rect.height() * 0.8 + adjustY2 else: self.direction = "x<y>" self.fromLocation.edges[self.boxName] = "bottom" self.toLocation.edges[self.boxName] = "right" x1 = self.fromLocation.rect.width() * 0.2 + adjustX1 y1 = adjustY1 + self.fromLocation.rect.height() x2 = adjustX2 + self.toLocation.rect.width() y2 = self.toLocation.rect.height() * 0.2 + adjustY2 self.direction = self.direction + " fLX:" + str( self.fromLocation.x()) + ",fLrx" + str( self.fromLocation.rect.x()) + ",fLrw" + str( self.fromLocation.rect.width()) + ",Lx" + str(x1) self.source = QPointF(x1, y1) self.dest = QPointF(x2, y2) self.line = QLineF(self.source, self.dest) self.line.setLength(self.line.length() - 5) @property def boxName(self): return self._boxName @boxName.setter def boxName(self, value): if not isinstance(value, str): raise ValueError('EdgeName must be an string!') self._boxName = value @property def guard(self): return self._guard @guard.setter def guard(self, value): if not isinstance(value, str): raise ValueError('EdgeName must be an string!') self._guard = value @property def reset(self): return self._reset @reset.setter def reset(self, value): if not isinstance(value, str): raise ValueError('EdgeName must be an string!') self._reset = value def toSaveJson(self): data = { "type": "Edge", "boxName": self.boxName, "strFromLocation": self.fromLocation.boxName, "strToLocation": self.toLocation.boxName, "guard": self.guard, "reset": self.reset, "style": self.style, "rotation": self.rotation() } return data @property def fromLocation(self): return self._fromLocation @fromLocation.setter def fromLocation(self, value): if value != None: if not isinstance(value, LocationItem): raise ValueError('LocationName must be a LocationItem!') self._fromLocation = value self.resetLine() @property def toLocation(self): return self._toLocation @toLocation.setter def toLocation(self, value): if value != None: if not isinstance(value, LocationItem): raise ValueError('LocationName must be a LocationItem!') self._toLocation = value self.resetLine() def parentWidget(self): return self.scene.views()[0] def itemChange(self, change, variant): if change != QGraphicsItem.ItemSelectedChange: global Dirty Dirty = True return QGraphicsLineItem.itemChange(self, change, variant) def mouseDoubleClickEvent(self, event): dialog = edgeItemDlg(self, self.parentWidget(), self.parentWidget(), self.scene, self.parentForm) dialog.exec_() def paint(self, QPainter, QStyleOptionGraphicsItem, QWidget_widget=None): # setPen pen = QPen() pen.setWidth(1) pen.setJoinStyle(Qt.MiterJoin) #让箭头变尖 QPainter.setPen(pen) # draw line QPainter.drawLine(self.line) ptextx = (self.line.x1() + self.line.x2()) / 2 ptexty = (self.line.y1() + self.line.y2()) / 2 ptexty -= 5 ptextx -= len(self.boxName) * 3 #QPainter.drawText(QPointF(ptextx, ptexty+20), self.direction) # setBrush brush = QBrush() brush.setColor(Qt.black) brush.setStyle(Qt.SolidPattern) QPainter.setBrush(brush) v = self.line.unitVector() v.setLength(5) v.translate(QPointF(self.line.dx(), self.line.dy())) n = v.normalVector() n.setLength(n.length() * 0.5) n2 = n.normalVector().normalVector() p1 = v.p2() p2 = n.p2() p3 = n2.p2() # 方法1 QPainter.drawLine(self.line) QPainter.drawPolygon(p1, p2, p3) if self.fromLocation is not None and self.toLocation is not None: if self.fromLocation.boxName == self.toLocation.boxName: QPainter.drawArc(self.arcx1, self.arcy1, 80, 80, self.minAngle * 16, self.spanAngle * 16) ptextx = self.arcTextx ptexty = self.arcTexty #QPainter.drawArc(self.arcx1, self.arcy1+100, 50, 50, 270*16, 89*16) #QPainter.drawArc(self.arcx1, self.arcy1+200, 50, 50, 0*16, 89*16) #QPainter.drawArc(self.arcx1, self.arcy1+300, 50, 50, 270*16, 180*16) #QPainter.drawArc(self.arcx1, self.arcy1+400, 50, 50, 270*16, 270*16) #QPainter.drawArc(self.arcx1, self.arcy1+500, 50, 50, 180*16, 89*16) QPainter.drawText(QPointF(ptextx, ptexty), self.boxName) #QPainter.drawRect(self.arcx1, self.arcy1, 50, 50) self.scene.update()
class GraphicEdge(QGraphicsPathItem): def __init__(self, edge_wrap, directed, parent=None): super().__init__(parent) self.edge_wrap = edge_wrap self.width = 3.0 self.pos_src = [0, 0] self.pos_dst = [0, 0] # 是否有向 self.directed = directed self.flag = 0 self.capacity = self.edge_wrap.capacity self.setAcceptHoverEvents(True) # 普通画图时的pen样式 self._n_pen = QPen(QColor("#000")) self._n_pen.setWidthF(self.width) # 画图时的pen样式 self._pen = self._n_pen # 悬浮时的pen样式 self._hover_pen = QPen(Qt.green) self._hover_pen.setWidthF(self.width) # 拖拽时的样式 self._pen_dragging = QPen(QColor("#000")) self._pen_dragging.setStyle(Qt.DashDotLine) self._pen_dragging.setWidthF(self.width) self._mark_brush = QBrush() self._mark_brush.setColor(Qt.green) self._mark_brush.setStyle(Qt.SolidPattern) self._normal_brush = QBrush() self._normal_brush.setColor(Qt.black) self._normal_brush.setStyle(Qt.SolidPattern) self.brush = self._normal_brush self.setFlag(QGraphicsItem.ItemIsSelectable) self.setZValue(-1) def set_src(self, x, y): self.pos_src = [x, y] def set_dst(self, x, y): self.pos_dst = [x, y] def calc_path(self): path = QPainterPath(QPointF(self.pos_src[0], self.pos_src[1])) # 起点 path.lineTo(QPointF(self.pos_dst[0], self.pos_dst[1])) # 终点 if self.directed: # 画箭头 self.line = QLineF(QPointF(self.pos_src[0], self.pos_src[1]), QPointF(self.pos_dst[0], self.pos_dst[1])) if self.flag == 0: self.line.setLength(self.line.length() - 20) else: self.line.setLength(self.line.length() - self.edge_wrap.end_item.r) v = self.line.unitVector() v.setLength(20) v.translate(QPointF(self.line.dx(), self.line.dy())) n = v.normalVector() n.setLength(n.length() * 0.5) n2 = n.normalVector().normalVector() p1 = v.p2() p2 = n.p2() p3 = n2.p2() # 方法2 arrow = QPolygonF([p1, p2, p3, p1]) path.addPolygon(arrow) # path = QPainterPath(QPointF(self.pos_src[0], self.pos_src[1])) # path.lineTo(self.pos_dst[0], self.pos_dst[1]) return path def boundingRect(self): return self.shape().boundingRect() def hoverEnterEvent(self, event: 'QGraphicsSceneHoverEvent'): self.brush = self._mark_brush self._pen = self._hover_pen self.update() def hoverLeaveEvent(self, event: 'QGraphicsSceneHoverEvent'): self.brush = self._normal_brush self._pen = self._n_pen self.update() def shape(self): # 设置宽度 这里用了100 很大 qps = QPainterPathStroker() qps.setWidth(100) return qps.createStroke(self.calc_path()) def paint(self, painter, graphics_item, widget=None): if self.edge_wrap.end_item is None: self.ensureVisible() self.setPath(self.calc_path()) path = self.path() painter.setPen(self._pen_dragging) painter.setBrush(self.brush) painter.drawPath(path) else: # 这画的才是连接后的线 self.flag = 1 self.setPath(self.calc_path()) # 设置路径 path = self.path() painter.setPen(self._pen) painter.setBrush(self.brush) painter.drawPath(path) self.flag = 0 painter.setFont(QFont("Times New Roman", 16)) painter.setPen(Qt.red) x = int((self.pos_src[0] + self.pos_dst[0]) / 2 - 17) y = int((self.pos_src[1] + self.pos_dst[1]) / 2 - 7) painter.drawText(x, y, "({}) {}".format(self.edge_wrap.id, self.capacity))
def drawRadar(selfself, qp): #set frame: qp.setBrush(QBrush(QColor(0, 0, 0), Qt.SolidPattern)) qp.drawRect(20, 10, 700, 700) pen_bold = QPen(QColor(102, 204, 255), 0.8, Qt.SolidLine) pen = QPen(QColor(102, 204, 255), 0.8, Qt.DashDotLine) pen_hide = QPen(QColor(0, 0, 0), 1.5, Qt.SolidLine) #add circle: qp.setPen(pen) qp.drawEllipse(QPointF(370, 360), 347, 347) #add scales: for i in range(1, 360): if i % 30 == 0: pass else: if i % 10 == 0: scaleLine = QLineF() scaleLine.setP1(QPointF(370, 360)) scaleLine.setAngle(i) scaleLine.setLength(347) qp.setPen(pen_bold) qp.drawLine(scaleLine) hideLine = QLineF() hideLine.setP1(QPointF(370, 360)) hideLine.setAngle(i) hideLine.setLength(337) qp.setPen(pen_hide) qp.drawLine(hideLine) else: scaleLine = QLineF() scaleLine.setP1(QPointF(370, 360)) scaleLine.setAngle(i) scaleLine.setLength(347) qp.setPen(pen_bold) qp.drawLine(scaleLine) hideLine = QLineF() hideLine.setP1(QPointF(370, 360)) hideLine.setAngle(i) hideLine.setLength(342) qp.setPen(pen_hide) qp.drawLine(hideLine) #add other circles: qp.setPen(pen) qp.drawEllipse(QPointF(370, 360), 277, 277) qp.setPen(pen) qp.drawEllipse(QPointF(370, 360), 207, 207) qp.setPen(pen) qp.drawEllipse(QPointF(370, 360), 137, 137) qp.setPen(pen) qp.drawEllipse(QPointF(370, 360), 67, 67) #add lines: qp.setPen(pen_bold) qp.drawLine(20, 360, 720, 360) qp.setPen(pen_bold) qp.drawLine(370, 10, 370, 710) angleLine1 = QLineF() angleLine1.setP1(QPointF(370, 360)) angleLine1.setAngle(30) angleLine1.setLength(347) qp.setPen(pen) qp.drawLine(angleLine1) angleLine2 = QLineF() angleLine2.setP1(QPointF(370, 360)) angleLine2.setAngle(60) angleLine2.setLength(347) qp.setPen(pen) qp.drawLine(angleLine2) angleLine3 = QLineF() angleLine3.setP1(QPointF(370, 360)) angleLine3.setAngle(120) angleLine3.setLength(347) qp.setPen(pen) qp.drawLine(angleLine3) angleLine4 = QLineF() angleLine4.setP1(QPointF(370, 360)) angleLine4.setAngle(150) angleLine4.setLength(347) qp.setPen(pen) qp.drawLine(angleLine4) angleLine5 = QLineF() angleLine5.setP1(QPointF(370, 360)) angleLine5.setAngle(210) angleLine5.setLength(347) qp.setPen(pen) qp.drawLine(angleLine5) angleLine6 = QLineF() angleLine6.setP1(QPointF(370, 360)) angleLine6.setAngle(240) angleLine6.setLength(347) qp.setPen(pen) qp.drawLine(angleLine6) angleLine7 = QLineF() angleLine7.setP1(QPointF(370, 360)) angleLine7.setAngle(300) angleLine7.setLength(347) qp.setPen(pen) qp.drawLine(angleLine7) angleLine8 = QLineF() angleLine8.setP1(QPointF(370, 360)) angleLine8.setAngle(330) angleLine8.setLength(347) qp.setPen(pen) qp.drawLine(angleLine8)
def drawArrows(self, painter): """Draws arrows on the board.""" for highlight in self.highlights: if highlight.Type == self.Arrow.Type: lineWidth = 10 sqSize = self.squareSize painter.setPen( QPen(highlight.color, lineWidth, Qt.SolidLine, Qt.RoundCap)) origin = highlight.origin target = highlight.target dx = target.x() - origin.x() dy = target.y() - origin.y() # Knight jumps if dx == sqSize.width() and dy == -2 * sqSize.height(): corner = QPoint(origin.x(), origin.y() - 2 * sqSize.height()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == 2 * sqSize.width() and dy == -sqSize.height(): corner = QPoint(origin.x() + 2 * sqSize.width(), origin.y()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == 2 * sqSize.width() and dy == sqSize.height(): corner = QPoint(origin.x() + 2 * sqSize.width(), origin.y()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == sqSize.width() and dy == 2 * sqSize.height(): corner = QPoint(origin.x(), origin.y() + 2 * sqSize.height()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == -sqSize.width() and dy == 2 * sqSize.height(): corner = QPoint(origin.x(), origin.y() + 2 * sqSize.height()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == -2 * sqSize.width() and dy == sqSize.height(): corner = QPoint(origin.x() - 2 * sqSize.width(), origin.y()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == -2 * sqSize.width() and dy == -sqSize.height(): corner = QPoint(origin.x() - 2 * sqSize.width(), origin.y()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner elif dx == -sqSize.width() and dy == -2 * sqSize.height(): corner = QPoint(origin.x(), origin.y() - 2 * sqSize.height()) line = QLineF(origin, corner) painter.drawLine(line) origin = corner # Other moves (and second part of knight jump) line = QLineF(origin, target) angle = line.angle() tip = line.p2() line.setLength(line.length() - 2 * lineWidth) painter.drawLine(line) tipOffset = line.p2() leftBase = QLineF() leftBase.setP1(tipOffset) leftBase.setLength(lineWidth) leftBase.setAngle(angle - 90) left = leftBase.p2() rightBase = QLineF() rightBase.setP1(tipOffset) rightBase.setLength(lineWidth) rightBase.setAngle(angle + 90) right = rightBase.p2() arrowHead = QPolygonF([left, right, tip]) path = QPainterPath() path.addPolygon(arrowHead) painter.fillPath(path, QBrush(highlight.color))
def _boundJoystick(self, point): limitLine = QLineF(self._center(), point) if (limitLine.length() > self.__maxDistance): limitLine.setLength(self.__maxDistance) return limitLine.p2()