def test_arrowannotation(self): item = ArrowItem() self.scene.addItem(item) item.setLine(QLineF(100, 100, 100, 200)) item.setLineWidth(5) item = ArrowItem() item.setLine(QLineF(150, 100, 150, 200)) item.setLineWidth(10) item.setArrowStyle(ArrowItem.Concave) self.scene.addItem(item) item = ArrowAnnotation() item.setPos(10, 10) item.setLine(QLineF(10, 10, 200, 200)) self.scene.addItem(item) item.setLineWidth(5) def advance(): clock = time.clock() * 10 item.setLineWidth(5 + math.sin(clock) * 5) item.setColor(QColor(Qt.red).lighter(100 + 30 * math.cos(clock))) self.singleShot(0, advance) advance() self.app.exec_()
def xsectArcRect1(arc, rect): """Find the single intersection point of the arc and the rectangle. arc -- Arc rect -- QRectF The arc start point is assumed to be at the center of the rect. Return a QPointF if the arc exits the rect exactly once and does not re-enter the rect. Else return None. """ # points where the line SEGMENT and the arc SEGMENT intersect xsectPoints = [] tl = rect.topLeft() tr = rect.topRight() bl = rect.bottomLeft() br = rect.bottomRight() cx = arc.centerX() cy = arc.centerY() r = arc.radius() for l in [QLineF(tl, tr), QLineF(tr, br), QLineF(br, bl), QLineF(bl, tl)]: for x, y in xsectLineCir(l, cx, cy, r): p = QPointF(x, y) if isPointOnArc(p, arc.center(), arc.start(), arc.span()): if isPointOnLineSeg(p, l): xsectPoints.append(p) if len(xsectPoints) == 1: return xsectPoints[0] else: return None
def __drawLine(self, value, duration, printvalue=True): ''' Draws a line depending on the type of the waveform. @param value: value to add to wave @param duration: integer, defines duration(length) of value in wave @param printvalue: bool, add values to waveform (for value-type waveforms only) ''' self.width = self.width + duration tmp = self.curPos self.curPos = QPointF(self.curPos.x() + duration, self.curPos.y()) if self.type == "bool": if value: self.addItem(QtGui.QGraphicsLineItem(QLineF(tmp, self.curPos))) else: self.addItem( QtGui.QGraphicsLineItem(tmp.x(), tmp.y() + self.vSpace, self.curPos.x(), self.curPos.y() + self.vSpace)) elif self.type in self.supportedTypes: if printvalue: text = QtGui.QGraphicsTextItem(str(value)) text.setFont(self.valFont) text.setDefaultTextColor(self.valFontColor) text.setPos(QPointF(tmp.x() + 4, tmp.y() - 5)) self.addItem(text) self.addItem(QtGui.QGraphicsLineItem(QLineF(tmp, self.curPos))) self.addItem( QtGui.QGraphicsLineItem(tmp.x(), tmp.y() + self.vSpace, self.curPos.x(), self.curPos.y() + self.vSpace))
def initShape(self): self.initHeads() #Line decoration offsetLine = QGraphicsLineItem(QLineF(90, 0, 90, 700)) asciiLine = QGraphicsLineItem(QLineF(480, 0, 480, 700)) #Add to scene self.__scene.addItem(offsetLine) self.__scene.addItem(asciiLine)
def boundingRect(self): if self._line is None: if self._orientation == Qt.Vertical: self._line = QLineF(0, self._value, self._length, self._value) else: self._line = QLineF(self._value, 0, self._value, self._length) r = QRectF(self._line.p1(), self._line.p2()) penw = self.pen().width() return r.adjusted(-penw, -penw, penw, penw)
def dummyLine(self, angle=None, length=None): if angle is not None and length is not None: pt1 = QLineF(QPointF(0.0, 0.0), QPointF(0.0, 1.0)) pt1.setAngle(angle) pt1.setLength(length + 16) self.__dummyLine = pt1 return self.__dummyLine = QLineF()
def generate_lines(self, line, steps=4, smooth=0.7, dampen=1.0): if steps <= 0: return [line] mid = (line.p1() + line.p2()) * 0.5 diff = (line.p2() - line.p1()) norm = QPointF(-diff.y(), diff.x()) mid += norm * (random.random() - 0.5) * smooth return self.generate_lines(QLineF( line.p1(), mid), steps - 1, smooth * dampen) + self.generate_lines( QLineF(mid, line.p2()), steps - 1, smooth * dampen)
def setHeads(self, pagesPerBlock): if self.heditor.pageOffView: self.setOffsetHead() else: self.setBlockHead() self.setPageHead(self.heditor.pagesPerBlock) linesize = 95 + (self.heditor.pagesPerBlock * (self.pagew + 2)) #Decoration headLine = QGraphicsLineItem(QLineF(0, 20, linesize, 20)) self.scene.addItem(headLine) headOffLine = QGraphicsLineItem(QLineF(90, 0, 90, 700)) self.scene.addItem(headOffLine)
def drawToolButtonMenuIndicator(self, option, painter, widget=None): arrow_rect = self.proxy().subControlRect(QStyle.CC_ToolButton, option, QStyle.SC_ToolButtonMenu, widget) text_color = option.palette.color(QPalette.WindowText if option.state & QStyle.State_AutoRaise else QPalette.ButtonText) button_color = option.palette.color(QPalette.Button) background_color = self.background_color(button_color, 0.5) painter.save() # draw separating vertical line if option.state & (QStyle.State_On|QStyle.State_Sunken): top_offset, bottom_offset = 4, 3 else: top_offset, bottom_offset = 2, 2 if option.direction == Qt.LeftToRight: separator_line = QLineF(arrow_rect.x()-3, arrow_rect.top()+top_offset, arrow_rect.x()-3, arrow_rect.bottom()-bottom_offset) else: separator_line = QLineF(arrow_rect.right()+3, arrow_rect.top()+top_offset, arrow_rect.right()+3, arrow_rect.bottom()-bottom_offset) light_gradient = QLinearGradient(separator_line.p1(), separator_line.p2()) light_gradient.setColorAt(0.0, ColorScheme.shade(self.background_top_color(button_color), ColorScheme.LightShade, 0.0)) light_gradient.setColorAt(1.0, ColorScheme.shade(self.background_bottom_color(button_color), ColorScheme.MidlightShade, 0.5)) separator_color = ColorScheme.shade(self.background_bottom_color(button_color), ColorScheme.MidShade, 0.0) painter.setRenderHint(QPainter.Antialiasing, False) painter.setPen(QPen(light_gradient, 1)) painter.drawLine(separator_line.translated(-1, 0)) painter.drawLine(separator_line.translated(+1, 0)) painter.setPen(QPen(separator_color, 1)) painter.drawLine(separator_line) # draw arrow arrow = QPolygonF([QPointF(-3, -1.5), QPointF(0.5, 2.5), QPointF(4, -1.5)]) if option.direction == Qt.LeftToRight: arrow.translate(-2, 1) else: arrow.translate(+2, 1) pen_thickness = 1.6 painter.setRenderHint(QPainter.Antialiasing, True) painter.translate(arrow_rect.center()) painter.translate(0, +1) painter.setPen(QPen(self.calc_light_color(background_color), pen_thickness, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawPolyline(arrow) painter.translate(0, -1) painter.setPen(QPen(self.deco_color(background_color, text_color), pen_thickness, Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin)) painter.drawPolyline(arrow) painter.restore()
def drawAxis(self, painter, rect, axis): """ Draws the axis for the given painter. :param painter | <QPainter> rect | <QRect> """ if not axis: return # draw the axis lines painter.save() pen = QPen(self.axisColor()) pen.setWidth(3) painter.setPen(pen) # draw the vertical line if axis.orientation() == Qt.Vertical: line = QLineF(rect.right(), rect.top(), rect.right(), rect.bottom()) painter.drawLine(line) painter.setFont(axis.labelFont()) for y, height, label in self._buildData.get('grid_h_labels', []): painter.drawText(0, y - height / 2.0, rect.width() - 3, height, Qt.AlignRight | Qt.AlignVCenter, label) painter.translate(0, rect.center().y()) painter.rotate(-90) painter.setFont(axis.titleFont()) painter.drawText(-rect.height() / 2, 0, rect.height(), rect.width(), Qt.AlignHCenter | Qt.AlignTop, axis.title()) # draw the horizontal line else: line = QLineF(rect.left(), rect.top(), rect.right(), rect.top()) painter.setFont(axis.titleFont()) painter.drawText(rect, Qt.AlignHCenter | Qt.AlignBottom, axis.title()) painter.drawLine(line) painter.setFont(axis.labelFont()) for x, width, label in self._buildData.get('grid_v_labels', []): painter.drawText(x - width / 2.0, 3, width, rect.height() - 6, Qt.AlignHCenter | Qt.AlignTop, label) painter.restore()
def qpainterpath_simple_split(path, t): """ Split a QPainterPath defined simple curve. The path must be either empty or composed of a single LineToElement or CurveToElement. Parameters ---------- path : QPainterPath t : float Point where to split specified as a percentage along the path Returns ------- splitpath: Tuple[QPainterPath, QPainterPath] A pair of QPainterPaths """ assert path.elementCount() > 0 el0 = path.elementAt(0) assert el0.type == QPainterPath.MoveToElement if path.elementCount() == 1: p1 = QPainterPath() p1.moveTo(el0.x, el0.y) return p1, QPainterPath(p1) el1 = path.elementAt(1) if el1.type == QPainterPath.LineToElement: pointat = path.pointAtPercent(t) l1 = QLineF(el0.x, el0.y, pointat.x(), pointat.y()) l2 = QLineF(pointat.x(), pointat.y(), el1.x, el1.y) p1 = QPainterPath() p2 = QPainterPath() p1.addLine(l1) p2.addLine(l2) return p1, p2 elif el1.type == QPainterPath.CurveToElement: c0, c1, c2, c3 = el0, el1, path.elementAt(2), path.elementAt(3) assert all(el.type == QPainterPath.CurveToDataElement for el in [c2, c3]) cp = [QPointF(el.x, el.y) for el in [c0, c1, c2, c3]] first, second = bezier_subdivide(cp, t) p1, p2 = QPainterPath(), QPainterPath() p1.moveTo(first[0]) p1.cubicTo(*first[1:]) p2.moveTo(second[0]) p2.cubicTo(*second[1:]) return p1, p2 else: assert False
def shape_line_intersection(shape, shape_pos, line): """ Return point of intersection between shape and line that is closest to line.p1(). """ intersections, point = [], QPointF() p1 = shape.pointAtPercent(0) + shape_pos r = shape.boundingRect() for t in np.linspace(0, 1.01, 50) % 1: p2 = shape.pointAtPercent(t) + shape_pos if QLineF(p1, p2).intersect(line, point) == QLineF.BoundedIntersection: intersections.append(QPointF(point)) p1 = p2 return min(intersections, key=lambda point: QLineF(line.p1(), point).length())
def draw_axes(self): self.remove_all_axes() for i in range(len(self.attributes)): axis_id = UserAxis + i a = self.add_axis(axis_id, line=QLineF(i, 0, i, 1), arrows=AxisStart | AxisEnd, zoomable=True) a.always_horizontal_text = True a.max_text_width = 100 a.title_margin = -10 a.text_margin = 0 a.setZValue(5) self.set_axis_title(axis_id, self.data_domain[self.attributes[i]].name) self.set_show_axis_title(axis_id, self.show_attr_values) if self.show_attr_values: attr = self.data_domain[self.attributes[i]] if attr.is_continuous: self.set_axis_scale(axis_id, self.attr_values[attr.name][0], self.attr_values[attr.name][1]) elif attr.is_discrete: attribute_values = get_variable_values_sorted( self.data_domain[self.attributes[i]]) attr_len = len(attribute_values) values = [ float(1.0 + 2.0 * j) / float(2 * attr_len) for j in range(len(attribute_values)) ] a.set_bounds((0, 1)) self.set_axis_labels(axis_id, labels=attribute_values, values=values)
def __init__(self, parent=None, line=None, **kwargs): Annotation.__init__(self, parent, **kwargs) self.setFlag(QGraphicsItem.ItemIsMovable) self.setFlag(QGraphicsItem.ItemIsSelectable) self.setFocusPolicy(Qt.ClickFocus) if line is None: line = QLineF(0, 0, 20, 0) self.__line = line self.__color = QColor(Qt.red) self.__arrowItem = ArrowItem(self) self.__arrowItem.setLine(line) self.__arrowItem.setBrush(self.__color) self.__arrowItem.setPen(QPen(Qt.NoPen)) self.__arrowItem.setArrowStyle(ArrowItem.Concave) self.__arrowItem.setLineWidth(5) self.__shadow = QGraphicsDropShadowEffect( blurRadius=5, offset=QPointF(1.0, 2.0), ) self.__arrowItem.setGraphicsEffect(self.__shadow) self.__shadow.setEnabled(True) self.__autoAdjustGeometry = True
def setLine(self, line): """ Set the arrow base line (a `QLineF` in object coordinates). """ if self.__line != line: self.__line = line # local item coordinate system geom = self.geometry().translated(-self.pos()) if geom.isNull() and not line.isNull(): geom = QRectF(0, 0, 1, 1) arrow_shape = arrow_path_concave(line, self.lineWidth()) arrow_rect = arrow_shape.boundingRect() if not (geom.contains(arrow_rect)): geom = geom.united(arrow_rect) if self.__autoAdjustGeometry: # Shrink the geometry if required. geom = geom.intersected(arrow_rect) # topLeft can move changing the local coordinates. diff = geom.topLeft() line = QLineF(line.p1() - diff, line.p2() - diff) self.__arrowItem.setLine(line) self.__line = line # parent item coordinate system geom.translate(self.pos()) self.setGeometry(geom)
def paint(self, painter, option, index): curr_class_dist = np.array(index.data(Qt.DisplayRole), dtype=float) curr_class_dist /= sum(curr_class_dist) painter.save() self.drawBackground(painter, option, index) rect = option.rect if sum(curr_class_dist) > 0: pw = 3 hmargin = 5 x = rect.left() + hmargin width = rect.width() - 2 * hmargin vmargin = 1 textoffset = pw + vmargin * 2 painter.save() baseline = rect.bottom() - textoffset / 2 text = str(index.data(Qt.DisplayRole)) option.displayAlignment = Qt.AlignCenter text_rect = rect.adjusted(0, 0, 0, -textoffset * 0) self.drawDisplay(painter, option, text_rect, text) painter.setRenderHint(QPainter.Antialiasing) for prop, color in zip(curr_class_dist, self.color_schema): if prop == 0: continue painter.setPen(QPen(QBrush(color), pw)) to_x = x + prop * width line = QLineF(x, baseline, to_x, baseline) painter.drawLine(line) x = to_x painter.restore() painter.restore()
def __on_lineGeometryChanged(self): # Possible geometry change from out of our control, for instance # item move as a part of a selection group. if not self.control.isControlActive(): line = self.item.line() p1, p2 = map(self.item.mapToScene, (line.p1(), line.p2())) self.control.setLine(QLineF(p1, p2))
def drawOneLine(self, timeChecked, occ): if not self.timeline.selDateMin: dateMin = self.timeline.baseDateMin dateMax = self.timeline.baseDateMax maxOcc = self.timeline.maxOcc else: dateMin = self.timeline.selDateMin dateMax = self.timeline.selDateMax maxOcc = self.timeline.maxOccZoom if (dateMax - dateMin) > 0: x = ((timeChecked - dateMin) * (self.ploter.width - self.m - self.yLeftMargin)) / ( dateMax - dateMin) + self.yLeftMargin y = (((maxOcc - occ) * (self.ploter.height - self.m - (self.m / 3))) / maxOcc) + (self.m / 3) if x <= self.yLeftMargin: x += 3 startY = self.ploter.height - self.m - 1 endY = y if y < self.ploter.height - self.m - 1: # Y level to show is biggest than penWidth startY -= 1 endY -= 1 if endY <= self.m / 3: # Y level is biggest than Y max value endY = self.m / 3 + 2 line = QLineF(x, startY, x, endY) self.painter.drawLines(line)
def paint(self, painter, option, widget=None): bounds = self.bounds for x in range(0, int(bounds.width()), self.size): self.lines.append( QLineF(x, bounds.y(), x, bounds.y() + bounds.height())) for y in range(0, int(bounds.height()), self.size): self.lines.append( QLineF(bounds.x(), y, bounds.x() + bounds.width(), y)) painter.setPen(self.pen) for line in self.lines: painter.drawLine(line)
def initHeads(self): self.offHead = QGraphicsTextItem() self.hexHead = QGraphicsTextItem() self.asciiHead = QGraphicsTextItem() #Set Color self.offHead.setDefaultTextColor(QColor(Qt.red)) self.hexHead.setDefaultTextColor(QColor(Qt.black)) self.asciiHead.setDefaultTextColor(QColor(Qt.darkCyan)) #Create Font self.font = QFont("Gothic") self.font.setFixedPitch(1) self.font.setBold(False) self.font.setPixelSize(14) #Set Font self.offHead.setFont(self.font) self.hexHead.setFont(self.font) self.asciiHead.setFont(self.font) #Set Text self.offHead.setPlainText("Offset") self.hexHead.setPlainText( "0 1 2 3 4 5 6 7 8 9 A B C D E F") self.asciiHead.setPlainText("Ascii") #Position self.offHead.setPos(20, 0) self.hexHead.setPos(95, 0) self.asciiHead.setPos(520, 0) #Add to scene self.__scene.addItem(self.offHead) self.__scene.addItem(self.hexHead) self.__scene.addItem(self.asciiHead) headLine = QGraphicsLineItem(QLineF(0, 20, 615, 20)) self.__scene.addItem(headLine)
def _updateTextAnchors(self): n = len(self._items) items = self._items dist = 15 shape = reduce(QPainterPath.united, [item.path() for item in items]) brect = shape.boundingRect() bradius = max(brect.width() / 2, brect.height() / 2) center = self.boundingRect().center() anchors = _category_anchors(items) self._textanchors = [] for angle, anchor_h, anchor_v in anchors: line = QLineF.fromPolar(bradius, angle) ext = QLineF.fromPolar(dist, angle) line = QLineF(line.p1(), line.p2() + ext.p2()) line = line.translated(center) anchor_pos = line.p2() self._textanchors.append((anchor_pos, anchor_h, anchor_v)) for i in range(n): self._updateTextItemPos(i)
def line_extended(line, distance): """ Return an QLineF extended by `distance` units in the positive direction. """ angle = line.angle() / 360 * 2 * math.pi dx, dy = unit_point(angle, r=distance) return QLineF(line.p1(), line.p2() + QPointF(dx, dy))
def angle(point1, point2): """Return the angle between the two points in range from -180 to 180. """ angle = QLineF(point1, point2).angle() if angle > 180: return angle - 360 else: return angle
def updatePosition(self, scene): pos0 = scene.posFromLonLat(self._lon0, self._lat0) pos1 = scene.posFromLonLat(self._lon1, self._lat1) deltaPos = pos1 - pos0 self.prepareGeometryChange() self.setLine(QLineF(QPointF(0.0, 0.0), deltaPos)) self.setPos(pos0)
def change_selector(self): if self.d2.isChecked(): self.scan_type = "continuous" self.selector = lambda start, end: self.camera_scene.addLine( QLineF(start, end)) else: self.scan_type = "3D" self.selector = self.select_rect
def _setup_plot(self): self.__replot_requested = False self.clear_plot() variables = list(self.varmodel_selected) if not variables: return coords = [self._get_data(var) for var in variables] coords = numpy.vstack(coords) p, N = coords.shape assert N == len(self.data), p == len(variables) axes = linproj.defaultaxes(len(variables)) assert axes.shape == (2, p) mask = ~numpy.logical_or.reduce(numpy.isnan(coords), axis=0) coords = coords[:, mask] X, Y = numpy.dot(axes, coords) X = plotutils.normalized(X) Y = plotutils.normalized(Y) pen_data, brush_data = self._color_data(mask) size_data = self._size_data(mask) shape_data = self._shape_data(mask) if self.jitter_value > 0: value = [0, 0.01, 0.1, 0.5, 1, 2][self.jitter_value] rstate = numpy.random.RandomState(0) jitter_x = (rstate.random_sample(X.shape) * 2 - 1) * value / 100 rstate = numpy.random.RandomState(1) jitter_y = (rstate.random_sample(Y.shape) * 2 - 1) * value / 100 X += jitter_x Y += jitter_y self._item = ScatterPlotItem( X, Y, pen=pen_data, brush=brush_data, size=size_data, shape=shape_data, antialias=True, data=numpy.arange(len(self.data))[mask] ) self._item._mask = mask self.viewbox.addItem(self._item) for i, axis in enumerate(axes.T): axis_item = AxisItem(line=QLineF(0, 0, axis[0], axis[1]), label=variables[i].name) self.viewbox.addItem(axis_item) self.viewbox.setRange(QtCore.QRectF(-1.05, -1.05, 2.1, 2.1))
def update_ends(self): try: self.prepareGeometryChange() self.setLine( QLineF(self.node1.edge_out_point(self), self.node2.edge_in_point(self))) except RuntimeError: # this gets called through QTimer.singleShot # and might already be deleted by Qt pass
def path_link_disabled(basepath): """ Return a QPainterPath 'styled' to indicate a 'disabled' link. A disabled link is displayed with a single disconnection symbol in the middle (--||--) Parameters ---------- basepath : QPainterPath The base path (a simple curve spine). Returns ------- path : QPainterPath A 'styled' link path """ segmentlen = basepath.length() px = 5 if segmentlen < 10: return QPainterPath(basepath) t = (px / 2) / segmentlen p1, _ = qpainterpath_simple_split(basepath, 0.50 - t) _, p2 = qpainterpath_simple_split(basepath, 0.50 + t) angle = -basepath.angleAtPercent(0.5) + 90 angler = math.radians(angle) normal = QPointF(math.cos(angler), math.sin(angler)) end1 = p1.currentPosition() start2 = QPointF(p2.elementAt(0).x, p2.elementAt(0).y) p1.moveTo(start2.x(), start2.y()) p1.addPath(p2) def QPainterPath_addLine(path, line): path.moveTo(line.p1()) path.lineTo(line.p2()) QPainterPath_addLine(p1, QLineF(end1 - normal * 3, end1 + normal * 3)) QPainterPath_addLine(p1, QLineF(start2 - normal * 3, start2 + normal * 3)) return p1
def paint(self, painter, option, widget=None): color, _ = Edge.Color.SELECTED if self.selected else Edge.Color.DEFAULT pen = self.pen() pen.setColor(color) pen.setBrush(QBrush(color)) pen.setWidth(np.clip(2 * self.weight(), .5, 4)) painter.setPen(pen) self.setPen(pen) if self.source == self.dest: return self.paintArc(painter, option, widget) if self.source.collidesWithItem(self.dest): return have_two_edges = len([ edge for edge in self.source.edges if self.source in edge and self.dest in edge and edge is not self ]) source_pos = self.source.pos() dest_pos = self.dest.pos() color = self.pen().color() painter.setBrush(color) point = shape_line_intersection(self.dest.shape(), dest_pos, QLineF(source_pos, dest_pos)) line = QLineF(source_pos, point) if have_two_edges: normal = line.normalVector() normal.setLength(15) line = QLineF(normal.p2(), point) self.label.setPos(line.pointAt(.5)) self.squares.placeBelow(self.label) self.setLine(line) painter.drawLine(line) # Draw arrow head self.arrowHead.clear() for point in self._arrowhead_points(line): self.arrowHead.append(point) painter.drawPolygon(self.arrowHead)
def _draw_grid(self): self.reset_pose() self._painter.setPen(self._grid_pen) xmin, ymin, xmax, ymax = self._bounds # Determine min/max x & y line indices: x_ticks = (int(xmin // self._grid_spacing), int(xmax // self._grid_spacing + 1)) y_ticks = (int(ymin // self._grid_spacing), int(ymax // self._grid_spacing + 1)) self._painter.drawLines([ QLineF(xmin, i * self._grid_spacing, xmax, i * self._grid_spacing) for i in range(*y_ticks) ]) self._painter.drawLines([ QLineF(i * self._grid_spacing, ymin, i * self._grid_spacing, ymax) for i in range(*x_ticks) ])