def qwtDrawStar1Symbols(painter, points, numPoints, symbol): size = symbol.size() painter.setPen(symbol.pen()) sqrt1_2 = np.sqrt(0.5) r = QRectF(0, 0, size.width(), size.height()) for pos in points: r.moveCenter(pos.toPoint()) c = QPointF(r.center()) d1 = r.width() / 2.0 * (1.0 - sqrt1_2) painter.drawLine(r.left() + d1, r.top() + d1, r.right() - d1, r.bottom() - d1) painter.drawLine(r.left() + d1, r.bottom() - d1, r.right() - d1, r.top() + d1) painter.drawLine(c.x(), r.top(), c.x(), r.bottom()) painter.drawLine(r.left(), c.y(), r.right(), c.y())
def colorBarRect(self, rect): """ Calculate the the rectangle for the color bar :param QRectF rect: Bounding rectangle for all components of the scale :return: Rectangle for the color bar """ cr = QRectF(rect) if self.__data.scaleDraw.orientation() == Qt.Horizontal: cr.setLeft(cr.left() + self.__data.borderDist[0]) cr.setWidth(cr.width() - self.__data.borderDist[1] + 1) else: cr.setTop(cr.top() + self.__data.borderDist[0]) cr.setHeight(cr.height() - self.__data.borderDist[1] + 1) sda = self.__data.scaleDraw.alignment() if sda == QwtScaleDraw.LeftScale: cr.setLeft(cr.right() - self.__data.margin - self.__data.colorBar.width) cr.setWidth(self.__data.colorBar.width) elif sda == QwtScaleDraw.RightScale: cr.setLeft(cr.left() + self.__data.margin) cr.setWidth(self.__data.colorBar.width) elif sda == QwtScaleDraw.BottomScale: cr.setTop(cr.top() + self.__data.margin) cr.setHeight(self.__data.colorBar.width) elif sda == QwtScaleDraw.TopScale: cr.setTop(cr.bottom() - self.__data.margin - self.__data.colorBar.width) cr.setHeight(self.__data.colorBar.width) return cr
class VLine(ChartItem): """ Simple vertical line without vertical bounds. :param parent: Parent item. """ def __init__(self, parent=None): super(VLine, self).__init__(parent) self.chartItemFlags = ChartItemFlags.FLAG_NO_AUTO_RANGE self._x = None self._label = None self._pen = QPen(QBrush(Qt.green), 1.0, Qt.SolidLine) self._pen.setCosmetic(True) self._brush = QBrush(QColor(255, 255, 255, 0)) finfo = np.finfo(np.float32) self.b_rect = QRectF(0, finfo.min / 2.0, 0, finfo.max) @property def label(self): return self._label def setX(self, x, label=None, color=QColor(Qt.red)): """ Sets the Vline's x value. :param x: abscissa value. :param label: :param color: """ self._x = x self.setPos(QPointF(self._x, 0)) if label is not None: self._label = label self._color = color self._pen = QPen(QBrush(color), 1.0, Qt.SolidLine) self._pen.setCosmetic(True) self._brush = QBrush(QColor(255, 255, 255, 0)) def visibleRangeChanged(self, rect): b = min(rect.bottom(), rect.top()) self.b_rect = QRectF(0, b - 10, 0, rect.height() + 20) self.prepareGeometryChange() def paint(self, p=QPainter(), o=QStyleOptionGraphicsItem(), widget=None): # p.setRenderHint(QPainter.Antialiasing) p.setPen(self._pen) p.setBrush(self._brush) p.drawLine( QLineF(QPointF(0, self.b_rect.bottom()), QPointF(0, self.b_rect.top()))) super(VLine, self).paint(p, o, widget) def __del__(self): _log.debug("Finalize VLine {}".format(self))
def setCornerRects(self, path): pos = QPointF(0.0, 0.0) for i in range(path.elementCount()): el = path.elementAt(i) if el.type in (QPainterPath.MoveToElement, QPainterPath.LineToElement): pos.setX(el.x) pos.setY(el.y) elif el.type == QPainterPath.CurveToElement: r = QRectF(pos, QPointF(el.x, el.y)) self.clipRects += [r.normalized()] pos.setX(el.x) pos.setY(el.y) elif el.type == QPainterPath.CurveToDataElement: if self.clipRects: r = self.clipRects[-1] r.setCoords( min([r.left(), el.x]), min([r.top(), el.y]), max([r.right(), el.x]), max([r.bottom(), el.y]), ) self.clipRects[-1] = r.normalized()
class InteractiveVerticalLine(ChartWidgetItem): """ Vertical Line which can be moved by mouse interaction. Usefull for timelines. """ positionChange = Signal(object) def __init__(self, parent=None): super(InteractiveVerticalLine, self).__init__(parent) self.setFlags( QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemSendsGeometryChanges ) self.chartItemFlags = ChartItemFlags.FLAG_NO_AUTO_RANGE self.setZValue(1e6) self.setAcceptHoverEvents(True) self._x = None self._label = None self._pen = QPen(QBrush(Qt.green), 1.0, Qt.SolidLine) self._pen.setCosmetic(True) self._brush = QBrush(QColor(255, 255, 255, 0)) @property def label(self): return self._label def setX(self, x, label=None, color=None): """ Sets the line's x value. :param x: abscissa value. :param label: :param color: """ if label is not None: self._label = label if color is not None: self._color = color self._pen = QPen(QBrush(color), 1.0, Qt.SolidLine) self._pen.setCosmetic(True) # self._brush = QBrush(QColor(255, 255, 255, 0)) if self._x != x: self._x = x self.setPos(QPointF(self._x, 0)) def visibleRangeChanged(self, rect): t = self.parentItem().transform() bb = 4 / t.m11() _log.debug("{}, {} -> {}".format(rect.bottom(), rect.height(), bb)) b = min(rect.bottom(), rect.top()) self.b_rect = QRectF(-bb, b, 2 * bb, rect.height()) self.prepareGeometryChange() def paint(self, p=QPainter(), o=QStyleOptionGraphicsItem(), widget=None): # p.setRenderHint(QPainter.Antialiasing) p.setPen(self._pen) p.setBrush(self._brush) p.drawLine( QLineF(QPointF(0, self.b_rect.bottom()), QPointF(0, self.b_rect.top())) ) p.setPen(Qt.transparent) p.drawRect(self.b_rect) if CONFIG.debug: p.setPen(Qt.yellow) p.drawRect(self.b_rect) def itemChange(self, change, value): if change == QGraphicsItem.ItemPositionChange: old_pos = self.pos() # value = value #.toPointF() e = InteractiveChangeEvent() e.position = value self.positionChange.emit(e) return QPointF(value.x(), old_pos.y()) return super(InteractiveVerticalLine, self).itemChange(change, value) def hoverEnterEvent(self, e): super(InteractiveVerticalLine, self).hoverEnterEvent(e) self._brush = QBrush(QColor(255, 255, 255, 40)) self.update() def hoverLeaveEvent(self, e): super(InteractiveVerticalLine, self).hoverLeaveEvent(e) self._brush = QBrush(QColor(255, 255, 255, 0)) self.update() def __del__(self): _log.debug("Finalize Interactive vLine {}".format(self))
def boundingRect(self): """ Calculate the bounding rectangle for a symbol at position (0,0). :return: Bounding rectangle """ rect = QRectF() pinPointTranslation = False if self.__data.style in (QwtSymbol.Ellipse, QwtSymbol.Rect, QwtSymbol.Hexagon): pw = 0.0 if self.__data.pen.style() != Qt.NoPen: pw = max([self.__data.pen.widthF(), 1.0]) rect.setSize(self.__data.size + QSizeF(pw, pw)) rect.moveCenter(QPointF(0.0, 0.0)) elif self.__data.style in ( QwtSymbol.XCross, QwtSymbol.Diamond, QwtSymbol.Triangle, QwtSymbol.UTriangle, QwtSymbol.DTriangle, QwtSymbol.RTriangle, QwtSymbol.LTriangle, QwtSymbol.Star1, QwtSymbol.Star2, ): pw = 0.0 if self.__data.pen.style() != Qt.NoPen: pw = max([self.__data.pen.widthF(), 1.0]) rect.setSize(QSizeF(self.__data.size) + QSizeF(2 * pw, 2 * pw)) rect.moveCenter(QPointF(0.0, 0.0)) elif self.__data.style == QwtSymbol.Path: if self.__data.path.graphic.isNull(): self.__data.path.graphic = qwtPathGraphic( self.__data.path.path, self.__data.pen, self.__data.brush) rect = qwtScaleBoundingRect(self.__data.path.graphic, self.__data.size) pinPointTranslation = True elif self.__data.style == QwtSymbol.Pixmap: if self.__data.size.isEmpty(): rect.setSize(self.__data.pixmap.pixmap.size()) else: rect.setSize(self.__data.size) pinPointTranslation = True elif self.__data.style == QwtSymbol.Graphic: rect = qwtScaleBoundingRect(self.__data.graphic.graphic, self.__data.size) pinPointTranslation = True elif self.__data.style == QwtSymbol.SvgDocument: if self.__data.svg.renderer is not None: rect = self.__data.svg.renderer.viewBoxF() if self.__data.size.isValid() and not rect.isEmpty(): sz = QSizeF(rect.size()) sx = self.__data.size.width() / sz.width() sy = self.__data.size.height() / sz.height() transform = QTransform() transform.scale(sx, sy) rect = transform.mapRect(rect) pinPointTranslation = True else: rect.setSize(self.__data.size) rect.moveCenter(QPointF(0.0, 0.0)) if pinPointTranslation: pinPoint = QPointF(0.0, 0.0) if self.__data.isPinPointEnabled: pinPoint = rect.center() - self.__data.pinPoint rect.moveCenter(pinPoint) r = QRect() r.setLeft(np.floor(rect.left())) r.setTop(np.floor(rect.top())) r.setRight(np.floor(rect.right())) r.setBottom(np.floor(rect.bottom())) if self.__data.style != QwtSymbol.Pixmap: r.adjust(-1, -1, 1, 1) return r
def activate(self, plot, plotRect, options=0x00): """ Recalculate the geometry of all components. :param qwt.plot.QwtPlot plot: Plot to be layout :param QRectF plotRect: Rectangle where to place the components :param options: Layout options """ self.invalidate() rect = QRectF(plotRect) self.__data.layoutData.init(plot, rect) if (not (options & self.IgnoreLegend) and plot.legend() and not plot.legend().isEmpty()): self.__data.legendRect = self.layoutLegend(options, rect) region = QRegion(rect.toRect()) rect = region.subtracted(QRegion( self.__data.legendRect.toRect())).boundingRect() if self.__data.legendPos == QwtPlot.LeftLegend: rect.setLeft(rect.left() + self.__data.spacing) elif self.__data.legendPos == QwtPlot.RightLegend: rect.setRight(rect.right() - self.__data.spacing) elif self.__data.legendPos == QwtPlot.TopLegend: rect.setTop(rect.top() + self.__data.spacing) elif self.__data.legendPos == QwtPlot.BottomLegend: rect.setBottom(rect.bottom() - self.__data.spacing) # +---+-----------+---+ # | Title | # +---+-----------+---+ # | | Axis | | # +---+-----------+---+ # | A | | A | # | x | Canvas | x | # | i | | i | # | s | | s | # +---+-----------+---+ # | | Axis | | # +---+-----------+---+ # | Footer | # +---+-----------+---+ # title, footer and axes include text labels. The height of each # label depends on its line breaks, that depend on the width # for the label. A line break in a horizontal text will reduce # the available width for vertical texts and vice versa. # expandLineBreaks finds the height/width for title, footer and axes # including all line breaks. dimTitle, dimFooter, dimAxes = self.expandLineBreaks(options, rect) if dimTitle > 0: self.__data.titleRect.setRect(rect.left(), rect.top(), rect.width(), dimTitle) rect.setTop(self.__data.titleRect.bottom() + self.__data.spacing) if (self.__data.layoutData.scale[QwtPlot.yLeft].isEnabled != self.__data.layoutData.scale[QwtPlot.yRight].isEnabled): self.__data.titleRect.setX(rect.left() + dimAxes[QwtPlot.yLeft]) self.__data.titleRect.setWidth(rect.width() - dimAxes[QwtPlot.yLeft] - dimAxes[QwtPlot.yRight]) if dimFooter > 0: self.__data.footerRect.setRect(rect.left(), rect.bottom() - dimFooter, rect.width(), dimFooter) rect.setBottom(self.__data.footerRect.top() - self.__data.spacing) if (self.__data.layoutData.scale[QwtPlot.yLeft].isEnabled != self.__data.layoutData.scale[QwtPlot.yRight].isEnabled): self.__data.footerRect.setX(rect.left() + dimAxes[QwtPlot.yLeft]) self.__data.footerRect.setWidth(rect.width() - dimAxes[QwtPlot.yLeft] - dimAxes[QwtPlot.yRight]) self.__data.canvasRect.setRect( rect.x() + dimAxes[QwtPlot.yLeft], rect.y() + dimAxes[QwtPlot.xTop], rect.width() - dimAxes[QwtPlot.yRight] - dimAxes[QwtPlot.yLeft], rect.height() - dimAxes[QwtPlot.xBottom] - dimAxes[QwtPlot.xTop], ) for axis in QwtPlot.AXES: if dimAxes[axis]: dim = dimAxes[axis] scaleRect = self.__data.scaleRect[axis] scaleRect.setRect(*self.__data.canvasRect.getRect()) if axis == QwtPlot.yLeft: scaleRect.setX(self.__data.canvasRect.left() - dim) scaleRect.setWidth(dim) elif axis == QwtPlot.yRight: scaleRect.setX(self.__data.canvasRect.right()) scaleRect.setWidth(dim) elif axis == QwtPlot.xBottom: scaleRect.setY(self.__data.canvasRect.bottom()) scaleRect.setHeight(dim) elif axis == QwtPlot.xTop: scaleRect.setY(self.__data.canvasRect.top() - dim) scaleRect.setHeight(dim) scaleRect = scaleRect.normalized() # +---+-----------+---+ # | <- Axis -> | # +-^-+-----------+-^-+ # | | | | | | # | | | | # | A | | A | # | x | Canvas | x | # | i | | i | # | s | | s | # | | | | # | | | | | | # +-V-+-----------+-V-+ # | <- Axis -> | # +---+-----------+---+ # The ticks of the axes - not the labels above - should # be aligned to the canvas. So we try to use the empty # corners to extend the axes, so that the label texts # left/right of the min/max ticks are moved into them. self.alignScales(options, self.__data.canvasRect, self.__data.scaleRect) if not self.__data.legendRect.isEmpty(): self.__data.legendRect = self.alignLegend(self.__data.canvasRect, self.__data.legendRect)