def init(self, parent): ''' ''' if self.control is None: self.control = qtLED() scene = QGraphicsScene() # self.control.setStyleSheet("qtLED { border-style: none; }"); # self.control.setAutoFillBackground(True) # system background color scene.setBackgroundBrush(QBrush(QColor(237, 237, 237))) self.control.setStyleSheet("border: 0px") self.control.setMaximumWidth(35) self.control.setMaximumHeight(35) x, y = 10, 10 rad = 20 cx = x + rad / 1.75 cy = y + rad / 1.75 brush = self.get_color(self.value.state, cx, cy, rad / 2) pen = QPen() pen.setWidth(0) self.led = scene.addEllipse(x, y, rad, rad, pen=pen, brush=brush ) self.control.setScene(scene) self.value.on_trait_change(self.update_object, 'state')
def p(painter, color): device = painter.device() width, height = device.width(), device.height() painter.setRenderHint(QPainter.Antialiasing) pen = QPen() pen.setWidth(thickness) if random: pen.setBrush(noise_brush) painter.setPen(pen) painter.setOpacity(opacity/100) def getpoints(x, y): if angle in [0, 180]: return (0, y), (width, y) if angle in [90, 270]: return (x, 0), (x, height) derp = max(height, width) deg = math.radians(angle) p1 = (x - derp*math.cos(deg), y + derp * math.sin(deg)) p2 = (x+derp*math.cos(deg), y - derp * math.sin(deg)) return p1, p2 for pos in range(spacing+thickness, max(height, width), spacing+thickness): x = pos if angle < 90 else width-pos y = pos (x1, y1), (x2, y2) = getpoints(x, y) painter.drawLine(x1, y1, x2, y2) return
def paintEvent(self, pe): painter = QPainter(self) painter.save() gradient = QLinearGradient() gradient.setStart(self._grad_start) gradient.setFinalStop(self._grad_end) gradient.setColorAt(0, QColor(230, 230, 230)) gradient.setColorAt(1, QColor(247, 247, 247)) brush = QBrush(gradient) painter.setBrush(brush) pen = QPen(Qt.black) pen.setWidth(1) painter.setPen(pen) painter.drawPath(self._painter_path) painter.restore() font = QFont() font.setFamily("Tahoma") font.setPixelSize(11) font.setBold(True) pen = QPen(Qt.darkGray) painter.setPen(pen) painter.setFont(font) self_rect = QRect(self.rect()) self_rect.moveTo(self._hor_margin, self._ver_margin // 2) painter.drawText(self_rect, Qt.AlignLeft, self._text)
def __init__(self, parent=None): """ Default class constructor. :param `parent`: Pointer to a parent widget instance. :type `parent`: `QGraphicsItem`_ """ super(BaseObject, self).__init__(parent) qDebug("BaseObject Constructor()") self.objPen = QPen() # QPen objPen; self.lwtPen = QPen() # QPen lwtPen; self.objLine = QLineF() # QLineF objLine; self.objRubberMode = int() # int objRubberMode; self.objRubberPoints = {} # QHash<QString, QPointF> objRubberPoints; self.objRubberTexts = {} # QHash<QString, QString> objRubberTexts; self.objID = int() # qint64 objID; self.objPen.setCapStyle(Qt.RoundCap) self.objPen.setJoinStyle(Qt.RoundJoin) self.lwtPen.setCapStyle(Qt.RoundCap) self.lwtPen.setJoinStyle(Qt.RoundJoin) self.objID = QDateTime.currentMSecsSinceEpoch()
def __init__(self, s, parent=None): """ Default class constructor. :param `s`: TOWRITE :type `s`: QRubberBand.Shape :param `parent`: Pointer to a parent widget instance. :type `parent`: `QWidget`_ """ super(SelectBox, self).__init__(s, parent) # private self._leftBrushColor = QColor() self._rightBrushColor = QColor() self._leftPenColor = QColor() self._rightPenColor = QColor() self._alpha = 255 # quint8 #: TODO: what is the initial int? self._dirBrush = QBrush() self._leftBrush = QBrush() self._rightBrush = QBrush() self._dirPen = QPen() self._leftPen = QPen() self._rightPen = QPen() self._boxDir = False #: TODO: is this initial bool value right? # Default values self.setColors(QColor(Qt.darkGreen), QColor(Qt.green), QColor(Qt.darkBlue), QColor(Qt.blue), 32)
class selectionLayer(layer): def __init__(self, size, dynamic, controller, prototypeLine, opaqueBack = False): layer.__init__(self,size,dynamic) self.controller = controller self.points = set() if opaqueBack: self.backgroundColor = Qt.white else: self.backgroundColor = Qt.transparent lineColor = QColor() lineColor.setNamedColor(prototypeLine.getAttribute('stroke')) lineColor.setAlphaF(float(prototypeLine.getAttribute('stroke-opacity'))) self.pen = QPen(lineColor) self.pen.setWidthF(prototypeLine.getAttribute('stroke-width')) def handleFrame(self, event, signals): return signals def refreshLines(self, points): self.points = points self.setDirty() def draw(self,painter): if len(self.points) >= self.controller.app.resolution_threshold: return pointList = list(self.points) self.image.fill(self.backgroundColor) painter.setPen(self.pen) painter.setRenderHint(QPainter.Antialiasing) lastA = self.controller.axisOrder[0] lastValues = self.controller.vData.getData(pointList,lastA) lastX = self.controller.axes[lastA].visAxis.axisLine.left() for a in self.controller.axisOrder[1:]: if not self.controller.axes[a].visible: continue values = self.controller.vData.getData(pointList,a) x = self.controller.axes[a].visAxis.axisLine.left() for y0,y1 in zip(lastValues,values): y0 = self.controller.axes[lastA].dataToScreen(y0) y1 = self.controller.axes[a].dataToScreen(y1) if len(y0) > len(y1): if len(y1) > 1: raise Exception("Mismatched number of values between attributes: %s %s" % (y0,y1)) else: for y00 in y0: painter.drawLine(lastX,y00,x,y1[0]) elif len(y1) > len(y0): if len(y0) > 1: raise Exception("Mismatched number of values between attributes: %s %s" % (y0,y1)) else: for y11 in y1: painter.drawLine(lastX,y0[0],x,y11) else: for i,y00 in enumerate(y0): painter.drawLine(lastX,y00,x,y1[i]) lastA = a lastValues = values lastX = x
def setChosen(self, ch): self.chosen = ch if ch: redPen = QPen(Qt.red) redPen.setWidth(2) self.setPen(redPen) else: self.setPen(QPen())
def paintEvent(self, pe): # make an arrow polygon right in the middle painter = QPainter(self) painter.setPen(Qt.NoPen) # draw the background transparent rect painter.save() painter.setOpacity(self.BACKGROUND_OPACITY) # get the rectangle coordinates it should extend over the whole width with only a portion at the center painter.setBrush(Qt.black) empty_space_percent = 1 - self.BACKROUND_HEIGHT_PERCENT rect_top = empty_space_percent / 2 * self.height() rect_height = self.BACKROUND_HEIGHT_PERCENT * self.height() painter.drawRect(0, rect_top, self.width(), rect_height) painter.restore() painter.setRenderHint(QPainter.Antialiasing) pen = QPen() pen.setWidth(self.ARROW_LINE_WIDTH) pen.setCapStyle(Qt.RoundCap) if self._mouse_inside: pen.setColor(self._hover_color) else: pen.setColor(self._normal_color) # get the arrow coords painter.setPen(pen) self_center = QPointF(self.width() / 2, self.height() / 2) # use this as the arrow tip for now if self._direction == self.LEFT: h_shift = self._arrow_width elif self._direction == self.RIGHT: h_shift = - self._arrow_width v_shift = self._arrow_height / 2 top_point = self_center + QPointF(h_shift, - v_shift) bottom_point = self_center + QPointF(h_shift, v_shift) painter.drawLine(top_point, self_center) painter.drawLine(self_center, bottom_point)
def drawPolyline(self): path = [mark.coordinate() for mark in self.markerObjects] pen = QPen(Qt.white) pen.setWidth(2) pen.setCosmetic(True) polyline = QGeoMapPolylineObject() polyline.setPen(pen) polyline.setPath(path) self.mapWidget.addMapObject(polyline)
def default_roi_pen(dashed=True,color=Qt.green): pen = QPen() if dashed: pen.setStyle(Qt.DashLine) pen.setBrush(color) pen.setCapStyle(Qt.RoundCap) pen.setJoinStyle(Qt.RoundJoin) return pen
def realRender(self, painter, renderPath): # TODO/PORT: Still needs work. """ TOWRITE :param `painter`: TOWRITE :type `painter`: `QPainter`_ :param `renderPath`: TOWRITE :type `renderPath`: `QPainterPath`_ """ color1 = self.objectColor() #QColor # lighter color color2 = color1.darker(150) #QColor # darker color # If we have a dark color, lighten it darkness = color1.lightness() #int threshold = 32 #int #TODO: This number may need adjusted or maybe just add it to settings. if darkness < threshold: color2 = color1 if not darkness: color1 = QColor(threshold, threshold, threshold) # lighter() does not affect pure black else : color1 = color2.lighter(100 + threshold) count = renderPath.elementCount() # int for i in range(0, count - 1): # for(int i = 0; i < count-1; ++i); elem = renderPath.elementAt(i) # QPainterPath::Element next = renderPath.elementAt(i + 1) # QPainterPath::Element if next.isMoveTo(): continue elemPath = QPainterPath() elemPath.moveTo(elem.x, elem.y) elemPath.lineTo(next.x, next.y) renderPen = QPen(QColor(0, 0, 0, 0)) renderPen.setWidthF(0) painter.setPen(renderPen) stroker = QPainterPathStroker() stroker.setWidth(0.35) stroker.setCapStyle(Qt.RoundCap) stroker.setJoinStyle(Qt.RoundJoin) realPath = stroker.createStroke(elemPath) # QPainterPath painter.drawPath(realPath) grad = QLinearGradient(elemPath.pointAtPercent(0.5), elemPath.pointAtPercent(0.0)) grad.setColorAt(0, color1) grad.setColorAt(1, color2) grad.setSpread(QGradient.ReflectSpread) painter.fillPath(realPath, QBrush(grad))
def draw(self, painter, offset, draw_mode=DRAW_MODE_NORMAL): if draw_mode != Bin.DRAW_MODE_RELEASE: # Рисуем контур контейнера pen = QPen() pen.setStyle(Qt.DashLine) painter.setPen(pen) # painter.drawRect(self.origin.x, self.origin.y, self.size.width, self.size.height) painter.drawRect(offset.x, offset.y, self.size.width, self.size.height) for image in self.images: # Rect(rect.origin + self.origin, rect.size, rect.pen).draw(painter=painter) # image.draw(painter=painter, offset=self.origin) image.draw(painter=painter, offset=offset)
def drawPolygon(self): path = [mark.coordinate() for mark in self.markerObjects] pen = QPen(Qt.white) pen.setWidth(2) pen.setCosmetic(True) polygon = QGeoMapPolygonObject() polygon.setPen(pen) fill = QColor(Qt.black) fill.setAlpha(65) polygon.setBrush(QBrush(fill)) polygon.setPath(path) self.mapWidget.addMapObject(polygon)
def paintEvent(self, pe): if not self._hover_rect: super(TrackerWebView, self).paintEvent(pe) else: super(TrackerWebView, self).paintEvent(pe) hover_rect = self._hover_rect self._fixRectForScroll(hover_rect) painter = QPainter(self) painter.save() pen = QPen(Qt.red) pen.setWidth(2) painter.setPen(pen) painter.drawRect(hover_rect) painter.restore() # draw green rects around the similar elements pen = QPen() pen.setWidth(2) for field_info in self._fields_info: painter.save() web_elements = field_info.web_elements color = field_info.color pen.setColor(color) painter.setPen(pen) for elem in web_elements: elem_rect = elem.absoluteGeometry() painter.drawRoundedRect(self._fixRectForScroll(elem_rect), 2, 2) painter.restore()
def init(self, parent): """ """ rad = self.factory.radius if not rad: rad = 20 if self.control is None: ctrl = qtLED() layout = QVBoxLayout() layout.addWidget(ctrl) scene = QGraphicsScene() # ctrl.setStyleSheet("qtLED { border-style: none; }"); # ctrl.setAutoFillBackground(True) # system background color scene.setBackgroundBrush(QBrush(QColor(237, 237, 237))) ctrl.setStyleSheet("border: 0px") ctrl.setMaximumWidth(rad + 15) ctrl.setMaximumHeight(rad + 15) x, y = 10, 10 cx = x + rad / 1.75 cy = y + rad / 1.75 brush = self.get_color(self.value.state, cx, cy, rad / 2) pen = QPen() pen.setWidth(0) self.led = scene.addEllipse(x, y, rad, rad, pen=pen, brush=brush) if self.factory.label: txt = QLabel(self.factory.label) layout.addWidget(txt) layout.setAlignment(txt, Qt.AlignHCenter) # txt = scene.addText(self.factory.label, QFont('arial 6')) # txt.setPos(cx, 10) ctrl.setScene(scene) layout.setAlignment(ctrl, Qt.AlignHCenter) self.value.on_trait_change(self.update_object, 'state') self.control = QWidget() self.control.setLayout(layout)
def drawRect(self): if len(self.markerObjects) < 2: return p1, p2 = self.markerObjects[:2] pen = QPen(Qt.white) pen.setWidth(2) pen.setCosmetic(True) fill = QColor(Qt.black) fill.setAlpha(65) rectangle = QGeoMapRectangleObject(p1.coordinate(), p2.coordinate()) rectangle.setPen(pen) rectangle.setBrush(QBrush(fill)) self.mapWidget.addMapObject(rectangle)
def drawWidget(self, qp): size = self.size() radx = size.width() rady = size.height() dot = min(radx, rady) / 2 pen = QPen() pen.setWidth(dot) # pen.setStyle(Qt.SolidLine) pen.setBrush(self.color) # pen.setCapStyle(Qt.RoundCap) # pen.setJoinStyle(Qt.RoundJoin) qp.setPen(pen) qp.drawLine(dot, dot, dot, dot)
def __init__(self, parent, child): ''' Create a new connection between a parent and a child item ''' super(Connection, self).__init__(parent) self.parent = parent self.child = child self._start_point = None self._end_point = None self._middle_points = [] pen = QPen() pen.setColor(Qt.blue) pen.setCosmetic(False) self.setPen(pen) self.parent_rect = parent.sceneBoundingRect() self.childRect = child.sceneBoundingRect() # Activate cache mode to boost rendering by calling paint less often self.setCacheMode(QGraphicsItem.DeviceCoordinateCache)
def paint(self, painter, _, ___): ''' Draw the comment symbol ''' rect = self.boundingRect() pen = QPen() pen.setStyle(Qt.DashLine) pen.setColor(Qt.darkGray) painter.setPen(pen) x, y, w, h = rect.x(), rect.y(), rect.width(), rect.height() if self.on_the_right: painter.drawLines([QPoint(w, y), QPoint(x, y), QPoint(x, y), QPoint(x, h), QPoint(x, h), QPoint(w, h)]) else: painter.drawLines([QPoint(x, y), QPoint(w, y), QPoint(w, y), QPoint(w, h), QPoint(w, h), QPoint(x, h)])
def setRoute(self, route): t = route.strip("{}") cs = t.split(";") path = list() for c in cs: c = c.strip("()") latitude = c[0:c.rfind(",")] longitude = c[c.rfind(",")+1:len(c)] path.append(QGeoCoordinate(float(latitude), float(longitude))) self.route = QGeoRoute() self.route.setPath(path) self.route_object = QGeoMapPolylineObject() self.route_object.setPath(path) pen = QPen(QtCore.Qt.red) pen.setWidth(5) self.route_object.setPen(pen) self.route_object.setZValue(1) self.addMapObject(self.route_object)
def paintEvent(self, event): painter = QtGui.QPainter(self) painter.setFont(self.font) # painter.setPen(QColor(200, 0, 100))#light grey painter.fillRect(event.rect(), self.background_color) p=QPen() p.setColor(QColor(100,100,100)) painter.setPen(p) rect=event.rect() rect.adjust(0,-1, self.adjust_width,1) painter.drawRect(rect) cw = self.parent() block = cw.firstVisibleBlock() blocknum = block.blockNumber() top = cw.blockBoundingGeometry(block).translated( cw.contentOffset()).top() bottom = top + int(cw.blockBoundingRect(block).height()) lineno=self.start while block.isValid() and top <= event.rect().bottom(): if block.isVisible() and bottom >= event.rect().top(): if blocknum>0: text=block.text() if not text.startswith(self.anti_tag): painter.drawText(0, top, self.width() - 2, self.fontMetrics().height(), QtCore.Qt.AlignRight, str(lineno)) lineno+=1 else: painter.drawText(0, top, self.width() - 2, self.fontMetrics().height(), QtCore.Qt.AlignRight, '...') block = block.next() top = bottom bottom = top + int(cw.blockBoundingRect(block).height()) blocknum += 1
def paintEvent(self, evt): # create a painter with paint(self) as painter: # adjust the width of the pen pen = QPen() pen.setWidth(5) painter.setPen(pen) # enable high quality antialiasing painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.HighQualityAntialiasing) # move the center of the coordinate system to the widgets center painter.translate(self.width() / 2, self.height() / 2) # rotate the coordinate system by the given angle painter.rotate(self.angle) # draw the spiral painter.drawPolyline(self.spiral) # end painting and free resources # update the angle self.angle += 30 self.angle %= 360
def paintEvent(self, pe): painter = QPainter(self) painter.save() background = QColor(55, 55, 55) brush = QBrush(background) painter.setOpacity(self._opacity) painter.setBrush(brush) painter.setPen(Qt.NoPen) painter.drawRect(self.rect()) painter.restore() # draw a bottom border painter.setPen(Qt.black) painter.drawLine(0, self.height(), self.width(), self.height()) # now the text pen = QPen(Qt.white) pen.setWidth(16) painter.setPen(pen) painter.setFont(QFont("Trebuchet MS", 16, QFont.Bold)) text_rect = QRect(self.rect()) text_rect.adjust(self._margin, self._margin, self._margin, self._margin) painter.drawText(text_rect, Qt.AlignLeft, self._message_str)
def paintEvent(self, event): painter = QPainter() painter.begin(self) painter.setRenderHint(QPainter.HighQualityAntialiasing) painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.SmoothPixmapTransform) self.img = QPixmap() if self.isChecked(): painter.setBrush(self.color1) painter.drawRoundedRect(QRect(-1, -1, 31, 31), 7, 7) painter.drawPixmap(QRect(-2, -5, 35, 40), self.img.fromImage(self.check)) else: pen = QPen() pen.setWidth(2) painter.setPen(pen) # hand draw rect painter.drawLine(QPoint(0, 0), QPoint(30, 0)) painter.drawLine(QPoint(30, 0), QPoint(30, 30)) painter.drawLine(QPoint(0, 0), QPoint(0, 30)) painter.drawLine(QPoint(0, 30), QPoint(30, 30)) painter.end()
def paintEvent(self, ev): if self.isEnabled(): color = self.color colorBorder = [0.4, 0.4, 0.4] else: color = [0.8, 0.8, 0.8] colorBorder = [0.7, 0.7, 0.7] painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) painter.setRenderHint(QPainter.HighQualityAntialiasing) if self.isChecked(): pen = QPen(QColor.fromRgbF(0.2, 0.2, 0.2)) pen.setWidth(2.0) else: pen = QPen(QColor.fromRgbF(colorBorder[0], colorBorder[1], colorBorder[2])) pen.setWidth(1.0) size = self.size() sizeCircle = 12.0 x = size.width() / 2.0 - (sizeCircle / 2.0) y = size.height() / 2.0 - (sizeCircle / 2.0) rect = QRectF(x, y, sizeCircle, sizeCircle) painter.setPen(pen) painter.setBrush(QColor.fromRgbF(color[0], color[1], color[2])) painter.drawEllipse(rect)
def drawCircle(self): if not len(self.markerObjects): return p1 = self.markerObjects[0] center = p1.coordinate() radius = 3000 # Meters if len(self.markerObjects) >= 2: radius = center.distanceTo(self.markerObjects[1].coordinate()) pen = QPen(Qt.white) pen.setWidth(2) pen.setCosmetic(True) circle = QGeoMapCircleObject(center, radius) circle.setPen(pen) fill = QColor(Qt.black) fill.setAlpha(65) circle.setBrush(QBrush(fill)) self.mapWidget.addMapObject(circle)
def _cutPen(self): if self.edit_mode: pen = QPen() pen.setWidthF(0.03) return pen else: pen = QPen(Qt.gray) pen.setWidthF(0.02) return pen
def paintEvent(self, event): painter = QPainter(self) # Фон painter_path = QPainterPath() painter_path.addRect(0, 0, self.width() - 1, self.height() - 1) painter.fillPath(painter_path, QBrush(QImage(':/main/background.png'))) if self.image: painter.drawText(10, 20, str(self.image.draw_scale)) painter.setTransform(QTransform(). scale(self.image.draw_scale, self.image.draw_scale). translate(self.image.draw_offset.x(), self.image.draw_offset.y())) old_pen = painter.pen() new_pen = QPen() new_pen.setColor(QColor(0, 150, 0)) painter.setPen(new_pen) self.image.draw(painter) painter.setPen(old_pen)
def __init__(self, size, dynamic, controller, prototypeLine, opaqueBack = False): layer.__init__(self,size,dynamic) self.controller = controller self.points = set() if opaqueBack: self.backgroundColor = Qt.white else: self.backgroundColor = Qt.transparent lineColor = QColor() lineColor.setNamedColor(prototypeLine.getAttribute('stroke')) lineColor.setAlphaF(float(prototypeLine.getAttribute('stroke-opacity'))) self.pen = QPen(lineColor) self.pen.setWidthF(prototypeLine.getAttribute('stroke-width'))
def routeFinished(self): if not self.routeReply.routes(): return route = QGeoMapRouteObject(self.routeReply.routes()[0]) routeColor = QColor(Qt.blue) routeColor.setAlpha(127) pen = QPen(routeColor) pen.setWidth(7) pen.setCosmetic(True) pen.setCapStyle(Qt.RoundCap) route.setPen(pen) self.mapWidget.addMapObject(route)
def _paint_crop(self, painter, option, index): """The cropped image """ source_rect = index.data(RectRole) crop_rect = self.CROP_RECT.translated(option.rect.topLeft()) angle = index.data(RotationRole) # Target rect with same aspect ratio as source source_aspect = float(source_rect.width()) / source_rect.height() crop_aspect = float(crop_rect.width()) / crop_rect.height() # True is the item has been rotated by a multiple of 90 degrees perpendicular = 1 == (angle / 90) % 2 # Some nasty logic to compute the target rect if perpendicular: crop_aspect = 1.0 / crop_aspect if source_aspect > 1.0: # Crop is wider than is is tall if crop_aspect > source_aspect: fit_to = 'height' f = 1.0 / source_aspect else: fit_to = 'width' f = source_aspect else: # Crop is taller than is is wide if crop_aspect < source_aspect: fit_to = 'width' f = source_aspect else: fit_to = 'height' f = 1.0 / source_aspect if perpendicular: if 'width' == fit_to: size = QSize(crop_rect.height(), crop_rect.height() / f) else: size = QSize(crop_rect.width() / f, crop_rect.width()) else: if 'width' == fit_to: size = QSize(crop_rect.width(), crop_rect.width() / f) else: size = QSize(crop_rect.height() / f, crop_rect.height()) target_rect = QRect(crop_rect.topLeft(), size) target_rect.moveCenter(option.rect.center()) # Draw rotated if angle: t = QTransform() t.translate(option.rect.width() / 2 + option.rect.left(), option.rect.height() / 2 + option.rect.top()) t.rotate(angle) t.translate(-option.rect.width() / 2 - option.rect.left(), -option.rect.height() / 2 - option.rect.top()) with painter_state(painter): if angle: painter.setTransform(t) painter.drawPixmap(target_rect, index.data(PixmapRole), source_rect) painter.setPen(QPen(Qt.white, 1, Qt.SolidLine)) painter.drawRect(target_rect)
def _draw_legend2(self, painter, labels): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque text_pen.setWidth(1) highlighted_text_pen = QPen() highlighted_text_pen.setColor(QColor(255, 255, 255)) # alpha=255=fully opaque highlighted_text_pen.setWidth(1) line_pen = QPen() line_pen.setCapStyle(Qt.RoundCap) line_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque line_pen.setWidth(2) row = col = 0 self.legend_labels_bounding_boxes = [] for data_ndx, label in sorted( zip(range(len(labels)),labels), key=lambda a:a[1]): if label: # One can hide a series' legend by using a blank label x = self.margin + col * self.max_legend_label_width + 3 y = self.legend_y_start + row * self.text_height # Draw coloured line line_pen.setColor(self.graph_colors[data_ndx % len(self.graph_colors)]) # alpha=255=fully opaque painter.setPen(line_pen) if data_ndx == self.ndx_best_serie: r = QRect(x-3, y-self.text_height+3, self.max_legend_label_width, self.text_height) painter.drawRect(r) painter.setPen(highlighted_text_pen) else: painter.drawLine(x,y+3,x+self.max_legend_label_width - 6,y + 3) painter.setPen(text_pen) painter.drawText(x,y, label) # Remember text bounding box r = QRect(x,y - self.text_height, self.max_legend_label_width, self.text_height) bb = painter.boundingRect(r,Qt.AlignLeft,label) # if label == 'TV': # painter.drawRect(r) self.legend_labels_bounding_boxes.append( (data_ndx,r) ) if not (col < self.legend_labels_per_line - 1): col = 0 row += 1 else: col += 1
def reload(self, order_overview_widget, all_ops, all_operations, sort=1): # mainlog.debug("reload...") progress = QProgressDialog(_("Collecting data..."), None, 0, len(all_ops) + 3, order_overview_widget) progress.setWindowTitle("Horse") progress.setMinimumDuration(0) progress.setWindowModality(Qt.WindowModal) progress.setValue(progress.value() + 1) progress.show() for i in self.items(): self.removeItem(i) self.posts_offsets = dict() self.drawn_operations_data = dict() self.cursor = QGraphicsRectItem(0, 0, 50, 300) self.cursor.setBrush(QBrush(QColor(208, 208, 255, 255))) self.cursor.setPen(QPen(Qt.transparent)) self.addItem(self.cursor) bar_width = 8 bar_height = int(bar_width * 60.0 / 8.0) ascent = QFontMetrics(self.base_font).ascent() ascent_big = QFontMetrics(self.base_font_big).ascent() post_ops = {} # mainlog.debug("reload...2") # z = 0 # for op,order_part,parts in all_operations: # z = op.planned_hours # z = order_part.deadline # z = order_part.qty # z = order_part.human_identifier # all_operations = map(lambda i:i[0],all_operations) y = 0 for opdef in all_ops: progress.setValue(progress.value() + 1) operations = filter( lambda op: op.operation_definition_id == opdef. operation_definition_id, all_operations) # We're only interested in the effort/time that remains # to be put on an operation. We're only interested in # the future. # We want the oeprations that are either # - ongoing # - ready to start. # In all cases we're only interested in operations # that are "active" if sort == 1: operations = sorted( operations, key=lambda op: op.deadline or date(3000, 1, 1)) elif sort == 2: operations = sorted( operations, key=lambda op: op.planned_hours * op.qty - op.done_hours) else: # Don't sort pass maximum = 16.0 #float ! small_hours = 0 op_ndx = 0 current_x = 50 bar_drawn = False total_done_hours = total_estimated = 0 # -------------------------------------------------------------- # Started operations bars_line = BarsLine(16, bar_width, bar_height, current_x, y, self, order_overview_widget) total_hours_to_do = 0 for op in filter(lambda op: op.done_hours > 0, operations): hours_to_do = max( 0, op.planned_hours * op.qty - op.done_hours) # max protects against reporting errors total_hours_to_do += hours_to_do total_estimated += op.planned_hours * op.qty total_done_hours += op.done_hours bars_line.add_bar(hours_to_do, QBrush(Qt.green), self._operation_hoover_description(op), False, None) # op.production_file.order_part) # -------------------------------------------------------------- bars_line_unstarted_operations = BarsLine(16, bar_width, bar_height, current_x + 30, y, self, order_overview_widget) total_hours_to_do_on_unstarted_operations = 0 for op in filter(lambda op: op.done_hours == 0, operations): hours_to_do = op.planned_hours * op.qty total_hours_to_do_on_unstarted_operations += hours_to_do total_estimated += hours_to_do bars_line_unstarted_operations.add_bar( hours_to_do, QBrush(Qt.yellow), self._operation_hoover_description(op), False, None) #op.production_file.order_part) y_start = y total = total_hours_to_do + total_hours_to_do_on_unstarted_operations if total > 0: self.drawn_operations_data[ opdef.operation_definition_id] = "{}h".format( int(round(total_estimated))) gi = QGraphicsSimpleTextItem( _("{} - Estimated to do : {}h; done : {}h").format( opdef.description, int(round(total)), int(round(total_done_hours)))) gi.setFont(self.base_font_big) gi.setPos(0, y - gi.boundingRect().height()) self.addItem(gi) th = gi.boundingRect().height() gi = QGraphicsLineItem(-ascent_big, y, 1024 + 2 * ascent_big, y) gi.setPen(QPen(Qt.black)) self.addItem(gi) y += th else: continue y_bars = y if total_hours_to_do > 0: # There's something to draw head = QGraphicsSimpleTextItem(_("Started")) head.setFont(self.base_font) head.setPos(current_x, y) self.addItem(head) y += head.boundingRect().height() y += bar_height bars_line.set_start_pos(current_x, y) bars_line.finish_bar() foot = QGraphicsSimpleTextItem( _("{}h").format(int(total_hours_to_do + 0.5))) foot.setFont(self.base_font) foot.setPos(current_x, y) self.addItem(foot) y += foot.boundingRect().height() current_x = max(current_x + bars_line.estimate_width(), head.boundingRect().right(), foot.boundingRect().right()) bar_drawn = True if total_hours_to_do_on_unstarted_operations > 0: if bars_line_unstarted_operations.estimate_width( ) + current_x > 1200: x = 50 y += ascent_big else: y = y_bars x = current_x + 50 head = QGraphicsSimpleTextItem(_("Not started yet")) head.setFont(self.base_font) head.setPos(x, y) self.addItem(head) y += head.boundingRect().height() y += bar_height bars_line_unstarted_operations.set_start_pos(x, y) bars_line_unstarted_operations.finish_bar() foot = QGraphicsSimpleTextItem( _("{}h").format( int(total_hours_to_do_on_unstarted_operations + 0.5))) foot.setFont(self.base_font) foot.setPos(x, y) self.addItem(foot) y += foot.boundingRect().height() bar_drawn = True y += 3 * ascent_big r = self.sceneRect() self.posts_offsets[opdef.operation_definition_id] = \ QRectF(r.x() - 2*ascent_big, y_start - 1.5*ascent_big, r.width() + 4*ascent_big, (y - ascent_big) - (y_start - 1.5*ascent_big) ) y += ascent_big # mainlog.debug("reload...3") import functools max_width = functools.reduce(lambda acc, po: max(acc, po.width()), self.posts_offsets.values(), 0) map(lambda po: po.setWidth(max_width), self.posts_offsets.values()) # for r in self.posts_offsets.values(): # gi = QGraphicsLineItem(r.x(),r.y(),r.x()+r.width(),r.y()) # gi.setPen(QPen(Qt.lightGray)) # self.addItem(gi) progress.close()
class LinesChart(QFrame): graph_colors = [Qt.GlobalColor.white, Qt.GlobalColor.blue, Qt.GlobalColor.red, Qt.GlobalColor.darkRed, Qt.GlobalColor.green, Qt.GlobalColor.darkGreen, Qt.GlobalColor.yellow] def __init__(self,parent=None): super(LinesChart,self).__init__(parent) self.timer = QTimer(self) self.timer.timeout.connect(self.timer_tick) # timerUpdate) self.timer.start(400) self.timer_ticks = 0 self.gride_lines_number = 0 self._create_pens() self.stacked = False self.title = "Sic transit gloria mundi" self.title_font = self.thinfont = QFont("Arial",10,QFont.Bold) self.margin = 10 self.total_width = 0 self.legend_labels_bounding_boxes = [] self.ndx_best_serie = -1 self.best_serie_intra_ndx = None self.no_draw = True # Set to True if we can't draw (because of numerical problems or non initialized data for example) self.data = None # When set to true, if the x axis values are dates # then, they'll be shown as month (so intead of 31/12/2014, # you'll get something like 12/14) self.x_axis_as_months = False self.set_mini_maxi(None, None) self.set_horizontal_ruler(None,None) self.forced_maxi = None self.forced_mini = None def set_title(self,t): self.title = t def timer_tick(self): self.timer_ticks += 1 self.update() def set_data(self,x_legends, legends,data): """ Sets the data to draw. :param x_legends: Labels to write on the X axis :param series_legends: Name of the various series. :param data: a list of series; each serie is a list of tuples : (x_coordinate, value). :return: """ mainlog.debug("({}) line_chart : set_data".format(self.title)) mainlog.debug(data) if len(legends) != len(data): raise Exception("The number of legends for data series ({}) is different than the number of series ({})".format(len(legends),len(data))) self.legends = legends self.x_legends = x_legends self.original_data = self.data = data # Compute the smallest and greatest value of the dataset # if self.forced_maxi == None and self.forced_mini == None: self.mini = 9999999999 self.maxi = 0 for l in self.data: if l: # There can be some None in the list, or the list might # even by made only of None's ! filtered = [x or 0 for x in l] if filtered: self.mini = min(min( filtered),self.mini) self.maxi = max(max( filtered),self.maxi) self.mini, self.maxi = self.clip_mini_maxi( self.mini, self.maxi) # if self.mini == self.maxi and self.forced_mini != None and self.forced_maxi != None: # self.mini, self.maxi = self.forced_mini, self.forced_maxi # Compute the sum of each "column" of data summed = [0] * len( data[0] ) for l in data: if l: summed = [(x or 0) + (y or 0) for x,y in zip(summed,l)] self.summed = summed self.highlighted_serie = None def clip_mini_maxi(self, mini, maxi): mainlog.debug("({}) Clipping {} {}, forced:{} {}".format( self.title, type(mini), type(maxi), type(self.forced_mini), type(self.forced_maxi))) if self.forced_mini != None and self.forced_maxi != None: mainlog.debug("Clipping to forced values {} {}".format( self.forced_mini, self.forced_maxi)) mini, maxi = min( mini, self.forced_mini), max( maxi, self.forced_maxi) return mini, maxi else: mainlog.debug("Clipping no clipping :{} {}".format(mini, maxi)) return mini, maxi def sizeHint(self): # QSizePolicy.expanding doesn't exapand as much as I want, # so I push myself :-) return QSize(4000,300) def _compute_legend_lengths(self, painter, legends): self.max_legend_label_width = 0 fm = painter.fontMetrics() for label in legends: self.max_legend_label_width = max(fm.boundingRect(label).width(), self.max_legend_label_width) self.space_between_legend_labels = 10 self.max_legend_label_width += self.space_between_legend_labels # a bit of room self.legend_labels_per_line = int(self.total_width / self.max_legend_label_width) if self.total_width % self.max_legend_label_width > 0: self.legend_labels_per_line += 1 self.legend_lines = len(legends) / self.legend_labels_per_line if len(legends) % self.legend_labels_per_line > 0: self.legend_lines += 1 self.legend_height = self.text_height * self.legend_lines def _compute_x_centers(self, nb_x, available_width): # ----------------------------- 29 # __1__ __2__ __3__ __4__ __5__ # 29/5 = 5.8 # 2.9, 8.7, 14.5, 20.3, 26.1 # mainlog.debug("_compute_x_centers({}, {})".format(nb_x, available_width)) if nb_x == 0: return [] step_width = float(available_width) / float(nb_x) all_x = [] for i in range(nb_x): all_x.append( self.x_base + step_width/2 + i * step_width ) return all_x def _compute_screen_lengths(self,painter,mini,maxi,x_steps): """ :param painter: QPainter :param mini: Minimum value that will be displayed on the Y axis :param maxi: Maximum value that will be displayed on the Y axis :param x_steps: Number of steps on the X axis :return: """ if x_steps > 0: assert 0 <= mini <= maxi, "We should have 0 <= {} <= {}".format(mini, maxi) # Measure regular font height fm = painter.fontMetrics() h = fm.boundingRect("A9j").height() self.text_height = h # Measure y_axis labels max width self.y_axis_label_width = fm.boundingRect(str(int(self.maxi))+"M").width() # Measure title font height base_font = painter.font() painter.setFont(self.title_font) r = QRect(self.margin,0,self.width() - 2*self.margin,self.height()) bb = painter.boundingRect(r,Qt.AlignLeft+Qt.TextWordWrap,self.title) painter.setFont(base_font) self.total_width = self.width() - 2*self.margin - self.y_axis_label_width # Lengths of the legend self._compute_legend_lengths(painter, self.legends) self.legend_y_start = self.margin + bb.height() # Distance between top of widget and top of chart self.yoffset = self.margin + bb.height() + self.legend_height self.total_height = self.height() - self.yoffset - self.margin - self.text_height # print total_width,total_height # Go from actual value to a screen position (without offset, see x/y_base) d = max(maxi,maxi - mini) self.no_draw = self.total_width < 1 or self.total_height < 1 or d <= 0 if self.no_draw: mainlog.debug("No draw because d:{} (mini {}, maxi {}) total_width:{} total_height:{}".format(d, mini, maxi, self.total_width, self.total_height )) return self.y_factor = float(min(self.total_height,self.total_width)) / d self.y_factor = float(self.total_height) / d if x_steps <= 3: self.x_factor = float(self.total_width) / float(3-1) elif x_steps > 1: self.x_factor = float(self.total_width) / float(x_steps - 1) else: self.x_factor = 0 # self.x_axis_offset = max(0, (self.total_width - x_steps * self.x_factor)/2) self.x_axis_offset = 0 # print self.maxi,self.mini,self.y_factor # The axis positions self.y_base = float(maxi) * self.y_factor + self.yoffset self.x_base = self.margin + self.y_axis_label_width + self.x_axis_offset # Now we compute the vertical axis step size. # Remember the graph is fit in the window # First we want each step to display a human firendly # value (so, no 12.3462, 24.68... but 10, 20, 30...) # And we start with an arbitrary number of steps # if self.mini == self.maxi: # steps = 6 # self.rounded_step_size = int(10 ** round(math.log10(self.maxi / steps))) or 1 # else: # steps = min(6, self.maxi - self.mini) or 1 # self.rounded_step_size = int(10 ** round(math.log10( (self.maxi - self.mini) / steps))) or 1 # # # if self.rounded_step_size > 1: # # # MAke sure the step size is small enough to have "steps" steps. # # while int(self.maxi / self.rounded_step_size) < steps: # self.rounded_step_size = int(self.rounded_step_size / 2) # # # Second, make sure the step is tall enough to let the text in # # while h > self.rounded_step_size * self.y_factor: # # mainlog.debug("{} > {} * {}".format(h, self.rounded_step_size, self.y_factor)) # self.rounded_step_size = self.rounded_step_size * 2 # # if self.maxi > 0: # step_size = (10 ** int(math.log10(self.maxi - 0.00001))) or 1 # mainlog.debug("Maxi={} Actual {}, new {}".format(self.maxi,self.rounded_step_size,step_size)) # self.rounded_step_size = step_size # else: # mainlog.debug("zero") log10 = math.log10( self.maxi) # This fix to make sure there is more than one step # in case the maxi is aligned on a power of 10. # In this case there will be 10 steps. if log10 - int(log10) == 0: fix = -1 else: fix = 0 step_size = 10 ** int(math.floor(log10) + fix) # If we rely only on power of 10, we might end up # with a small number of steps (e.g. 2). That is # correct but unpleasant to look at. To avoid # this, I increase the size of steps to reach # a minimum number of steps. # Dividing by two a power of 10 make sure we'll keep # "human readable" steps (1/2, 1/4, 1/8,...) MINIMUM_NUMBER_OF_STEPS = 4 while self.maxi / step_size < MINIMUM_NUMBER_OF_STEPS: # number of steps < MINIMUM_NUMBER_OF_STEPS step_size = step_size / 2 # Second, make sure the step is tall enough to let the text in while h > step_size * self.y_factor: # mainlog.debug("{} > {} * {}".format(h, self.rounded_step_size, self.y_factor)) step_size = step_size * 2 self.rounded_step_size = step_size self.x_centers = self._compute_x_centers(len(self.data[0]), self.total_width) def _compute_lengths(self,painter): self._compute_screen_lengths(painter,self.mini,self.maxi,len(self.data[0])) def leaveEvent( self, q_leave_event): if self.ndx_best_serie: self.ndx_best_serie = -1 self.update() def leaveEvent(self, event): self.ndx_best_serie = None self.best_serie_intra_ndx = None self.update() def mouseMoveEvent ( self, q_mouse_event): if not self.data or self.no_draw: return p = q_mouse_event.pos() # No need to highlight a serie if there's only one # in the graph. self.ndx_best_serie = -1 self.best_serie_intra_ndx = None if len(self.data) >= 1: ndx,serie = self._locate_legend(p.x(), p.y()) if not serie: # mainlog.debug("Trying to locate on graph") serie,self.best_serie_intra_ndx = self.locate_serie(None, p.x(), p.y()) if serie: #mainlog.debug("Located serie : {}".format(serie)) ndx = self.data.index(serie) # 2014/04/14 13:45:43 [DEBUG] Locate legend data_ndx:2 TO 77481144 - 20 # 2014/04/14 13:45:43 [DEBUG] mouseMove : Highlighting another serie found ndx:1 locate_ndx:2 77481144 # 2014/04/14 13:45:43 [DEBUG] _draw_legend: Highlighting serie ndx=1 77481144 if serie and self.ndx_best_serie != ndx: self.ndx_best_serie = ndx # self.data.index(serie) # mainlog.debug("mouseMove : Highlighting another serie found ndx:{} locate_ndx:{} {} loacte:{}".format(self.ndx_best_serie, ndx, id(serie), id(self.data[ndx]))) self.update() def _locate_legend(self, x, y): for i in range(len(self.legend_labels_bounding_boxes)): data_ndx,bb = self.legend_labels_bounding_boxes[i] if bb.contains(x,y): # mainlog.debug(u"Locate legend data_ndx:{} {} {} - {}".format( data_ndx,self.legends[data_ndx], id(self.data[data_ndx]),i)) return data_ndx, self.data[data_ndx] return None,None def locate_serie(self, painter, x, y): """ Find the serie which is closes to the x,y point """ if len(self.x_legends) <= 1: return None, None # y = self.height() - y screen_x_step = float(self.total_width) / len(self.x_legends) # The x corrdinates can be outside the graph area. # So I use som min and max to have an index in the serie's range x_ndx = min(len(self.data[0])-1, int(max(0, (x - self.margin - self.y_axis_label_width) / screen_x_step))) x_ndx1 = min( len(self.data[0])-1, x_ndx+1) delta_x = x - self.margin - self.y_axis_label_width - (x_ndx * screen_x_step ) # print "{}-{} -> {} - {} d={}".format(x,y,x_ndx,x_ndx1,delta_x) best_d = 999999999 best_serie = None for serie in self.data: if serie[x_ndx] is not None and serie[x_ndx1] is not None: y0 = serie[x_ndx] * self.y_factor y1 = serie[x_ndx1] * self.y_factor # Screen slope slope = (y1 - y0) / screen_x_step sy = self.y_base - ( y0 + slope * delta_x) d = (sy - y ) ** 2 # print d if d < best_d: best_d = d best_serie = serie return best_serie,x_ndx def _item_coordinates_lines(self, ndx_serie, ndx_in_serie): assert ndx_serie >= 0 and ndx_serie < len(self.data), "Incorrect ndx_serie ({})".format(ndx_serie) serie = self.data[ndx_serie] x = self.x_centers[ndx_in_serie] y_top = float(serie[ndx_in_serie]) * self.y_factor return x, y_top def _draw_selected_items_in_series(self, painter): fm = painter.fontMetrics() pen = QPen() pen.setWidth(1) pen.setColor(Qt.GlobalColor.white) painter.setPen(pen) # We assume all series have the very same number of values # and all values on the same index are drawn on the same X # coordinate ndx_serie = self.best_serie_intra_ndx aesthetic_shift = 5 if ndx_serie is not None: to_draw = [] for i in range(len(self.data)): x, y = self._item_coordinates_lines(i, ndx_serie) #mainlog.debug("{} {}".format(ndx_serie,i)) v = self.data[i][ndx_serie] text = str(int(v)) to_draw.append( (self.y_base - y, text) ) last_y = 100000 for y, text in sorted( to_draw, key=lambda z : z[0], reverse=True): r = QRect(x + aesthetic_shift,0,1000,1000) bb = painter.boundingRect(r,Qt.AlignLeft,text) if bb.right() > self.width(): x = x - bb.width() - 2*aesthetic_shift# left align if y + bb.height() > last_y: y = last_y - bb.height() fill_color = QColor(16, 16, 48) fill_color.setAlpha(196) brush = QBrush(fill_color) margin = 2 r = QRect(x + aesthetic_shift - margin, y - aesthetic_shift - bb.height() - margin, bb.width() + 2*margin, bb.height() + 2*margin) painter.fillRect(r, brush) painter.drawText(x + aesthetic_shift, y - aesthetic_shift, text) last_y = y x, y = self._item_coordinates_lines(0, ndx_serie) qp = QPainterPath() qp.moveTo(x, self.y_base) qp.lineTo(x, self.y_base - self.total_height) painter.drawPath(qp) def _draw_serie(self, painter, ndx_serie, color): serie = self.data[ndx_serie] if not serie: return qp = QPainterPath() # qp.addRect(2,2,total_width-4,total_height-4) x = float(0) * self.x_factor y = serie[0] * self.y_factor qp.moveTo(self.x_centers[0],self.y_base - y) # print y_base for i in range(1,len(serie)): x = float(i) * self.x_factor y = float(serie[i]) * self.y_factor qp.lineTo(self.x_centers[i], self.y_base-y) pen = QPen() pen.setColor(color) if ndx_serie == self.ndx_best_serie: pen.setWidth(6) else: pen.setWidth(2) painter.setPen(pen) painter.drawPath(qp) # self.max_legend_label_width = 0 # fm = painter.fontMetrics() # for label in legends: # self.max_legend_label_width = max(fm.boundingRect(label).width(), # self.max_legend_label_width) # self.max_legend_label_width += 10 # a bit of room # self.legend_labels_per_line = int(self.total_width / self.max_legend_label_width) # self.legend_lines = len(legends) / self.legend_labels_per_line # if len(legends) % self.legend_labels_per_line > 0: # self.legend_lines += 1 # self.legend_height = self.text_height * self.legend_lines def _draw_legend2(self, painter, labels): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque text_pen.setWidth(1) highlighted_text_pen = QPen() highlighted_text_pen.setColor(QColor(255, 255, 255)) # alpha=255=fully opaque highlighted_text_pen.setWidth(1) line_pen = QPen() line_pen.setCapStyle(Qt.RoundCap) line_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque line_pen.setWidth(2) row = col = 0 self.legend_labels_bounding_boxes = [] for data_ndx, label in sorted( zip(range(len(labels)),labels), key=lambda a:a[1]): if label: # One can hide a series' legend by using a blank label x = self.margin + col * self.max_legend_label_width + 3 y = self.legend_y_start + row * self.text_height # Draw coloured line line_pen.setColor(self.graph_colors[data_ndx % len(self.graph_colors)]) # alpha=255=fully opaque painter.setPen(line_pen) if data_ndx == self.ndx_best_serie: r = QRect(x-3, y-self.text_height+3, self.max_legend_label_width, self.text_height) painter.drawRect(r) painter.setPen(highlighted_text_pen) else: painter.drawLine(x,y+3,x+self.max_legend_label_width - 6,y + 3) painter.setPen(text_pen) painter.drawText(x,y, label) # Remember text bounding box r = QRect(x,y - self.text_height, self.max_legend_label_width, self.text_height) bb = painter.boundingRect(r,Qt.AlignLeft,label) # if label == 'TV': # painter.drawRect(r) self.legend_labels_bounding_boxes.append( (data_ndx,r) ) if not (col < self.legend_labels_per_line - 1): col = 0 row += 1 else: col += 1 def _draw_legend(self, painter, labels): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque text_pen.setWidth(1) highlighted_text_pen = QPen() highlighted_text_pen.setColor(QColor(255, 255, 255)) # alpha=255=fully opaque highlighted_text_pen.setWidth(1) line_pen = QPen() line_pen.setCapStyle(Qt.RoundCap) line_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque line_pen.setWidth(2) max_width = 0 fm = painter.fontMetrics() for label in labels: max_width = max(fm.boundingRect(label).width(), max_width) y_room = int(self.height() * 0.5 / self.text_height) nb_columns = int( len(labels) / y_room) if len(labels) % y_room > 0: nb_columns += 1 y_room = y_room * self.text_height x = self.margin + self.total_width - nb_columns * (max_width + 10) # 100 / 20 = 5 entry per column # 17 / 5 = 3 => 4 columns # print self.height() * 0.5, " ", len(labels), " ", nb_columns, " y_room:", y_room y = 0 i = 0 y_offset = self.yoffset self.legend_labels_bounding_boxes = [] # Draw a background rectanlge behin the legend fill_color = QColor(16,16,48) fill_color.setAlpha(196) brush = QBrush(fill_color) h = y_room w = nb_columns * (max_width + 10) if nb_columns == 1: h = len(labels) * self.text_height r = QRect(x-3, y_offset - self.text_height , w, h + 6) painter.fillRect(r,brush) sorted_labels = sorted( zip( range(len(labels)), labels, map(id,self.data)), lambda a,b:cmp(a[1],b[1])) # mainlog.debug( sorted_labels) # We sort labels on their names (but keep the indices right) for data_ndx, label in sorted( zip(range(len(labels)),labels), lambda a,b:cmp(a[1],b[1])): # Draw coloured line line_pen.setColor(self.graph_colors[data_ndx % len(self.graph_colors)]) # alpha=255=fully opaque painter.setPen(line_pen) if data_ndx == self.ndx_best_serie: r = QRect(x-3, y_offset+ y-self.text_height+3, max_width + 6, self.text_height) painter.drawRect(r) painter.setPen(highlighted_text_pen) else: painter.drawLine(x,y_offset+y+3,x+max_width,y_offset+y + 3) painter.setPen(text_pen) painter.drawText(x,y_offset+y,label) # Remember text bounding box r = QRect(x,y_offset+y - self.text_height,max_width,self.text_height) # if label == "TO": # painter.drawRect(r) bb = painter.boundingRect(r,Qt.AlignLeft,label) # bb.adjust(-5,-5,+5,+5) # print label,label_ndx,r.x(), r.y(), r.width(), r.height() self.legend_labels_bounding_boxes.append( (data_ndx,bb) ) if y >= y_room - self.text_height: y = 0 x += max_width + 10 else: y += self.text_height i += 1 def _create_pens(self): self.axis_text_pen = QPen() self.axis_text_pen.setCapStyle(Qt.RoundCap) self.axis_text_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque self.axis_text_pen.setWidth(1) def _draw_x_axis_dates(self, painter, l): def months_between(a,b): """ Nb of months, inclusive. """ if a > b: a,b = b,a if a.year == b.year: return b.month - a.month + 1 else: m = (12 - a.month + 1) + (b.month + 1) my = (b.year - a.year - 1) * 12 return m + my if not l or len(l) <= 2: return l fm = painter.fontMetrics() char_width = fm.boundingRect("9").width() nbchars = self.total_width / char_width nb_days = (l[-1] - l[0]).days if nb_days <= 10 and not self.x_axis_as_months: return l # mainlog.debug("Too many days") nb_months = months_between(l[0], l[-1]) if nb_months < (nbchars / len("MM/YY")): old_d = l[0] nl = [short_my(old_d)] # Will have the same length as l # print l[1:-1] for d in l[1:len(l)]: if d.month != old_d.month: if d.year != old_d.year: nl.append(short_my(d)) else: nl.append(str(d.month)) old_d = d else: nl.append("") if len(l) != len(nl): mainlog.error("something is wrong") return nl mainlog.debug("Too many months") nb_years = l[-1].year - l[0].year + 1 old_d = l[0] nl = [short_my(old_d)] # Will have the same length as l for d in l[1:len(l)]: if d.year != old_d.year: nl.append(short_my(d)) old_d = d else: nl.append("") return nl def _draw_x_axis(self, painter, labels): if not labels: return if isinstance(labels[0],date): # In this case we expect to have, for example, a label per day # Of course that's too many to draw, hence this "dithering" dithered_labels = [] # 12 expresses a "density" which allows us to switch between days and month # steps. Ideally we should generalize that to weeks, years... if len(labels) > 12: dithered_labels.append(labels[0]) for i in range(1,len(labels)): if labels[i].month != labels[i-1].month: dithered_labels.append(labels[i]) else: dithered_labels.append(None) labels = dithered_labels # mainlog.debug(labels) def short_my(d): if d: return u"{}/{:0>02}".format(d.month,d.year % 100) else: return "" # labels = self._draw_x_axis_dates(painter, labels) # labels = [short_my(l) for l in labels] old_d = labels[0] nl = [short_my(old_d)] # Will have the same length as l for d in labels[1:len(labels)]: if d and d.month != old_d.month: if d.year != old_d.year: nl.append(short_my(d)) else: nl.append(str(d.month)) old_d = d else: nl.append("") # Dithering == cleraing unwanted values labels = nl max_height = 0 total_label_width = 0 fm = painter.fontMetrics() for label in labels: br = fm.boundingRect(str(label)) max_height = max(br.height(), max_height) total_label_width += br.width() painter.setPen(self.axis_text_pen) last_x = -1 last_label = None for i in range(len(labels)): label = str(labels[i]) w = fm.boundingRect(label).width() x = self.x_centers[i] - w / 2 # Somehow, the width of an empty string is not 0 :-) if label and last_label != label and x > last_x: # Avoid that this label overlaps the previous one painter.drawText(x, self.y_base + max_height, label) last_x = x + w - 1 last_label = label if label: painter.drawLine(self.x_centers[i], self.y_base + 2, self.x_centers[i], self.y_base - 2) # else: # mainlog.debug("Skipping label={} x={} last_x={}".format(label, x, last_x)) def _draw_over_grid(self,painter): # painter.setRenderHint(QPainter.Antialiasing, False) line_color = QColor(60, 20, 200, 255) flat_structure = QColor(20,20,255,128) line_color = flat_structure w = min(self.height(), self.width()) / 20 m = self.margin / 2 x0 = m x1 = m + w x15 = m + 9*w x2 = self.width() - m - w x3 = self.width() - m y0 = m y1 = m + w y15 = m + 5*w y2 = self.height() - m - w y3 = self.height() - m # ---------------------------------------------------------------------- d = w / 4 p = [ (x0,y15+d), (x0,y1), (x1,y0), (x15+2*d,y0), # / (x15+d,y0+d), # ____/ (x1,y0+d), # / (x0+d,y1), # | (x0+d,y15), # | (x0,y15+d) # _| ] qp = QPainterPath() qp.moveTo( p[0][0], p[0][1],) for i in range(1,len(p)): qp.lineTo( p[i][0], p[i][1],) qp.closeSubpath() painter.fillPath(qp,QBrush(QColor(20,20,255,128))) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(line_color) # alpha=255=fully opaque pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp) # --------------------------------------------------------- qp = QPainterPath() p = [ (x0,y1), (x1,y0), (x2,y0), (x3,y1), (x3,y2), (x2,y3), (x1,y3), (x0,y2), (x0,y1)] qp.moveTo( p[0][0], p[0][1],) for i in range(1,len(p)): qp.lineTo( p[i][0], p[i][1],) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(QColor(0, 0, 80, 196)) # alpha=255=fully opaque pen.setWidth(5) painter.setPen(pen) painter.drawPath(qp) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(line_color) # alpha=255=fully opaque pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp) def _draw_grid(self,painter, y_base, width, height, steps): m = int(self.maxi / self.rounded_step_size) if self.timer.isActive(): self.gride_lines_number = self.timer_ticks if self.gride_lines_number >= m: self.timer.stop() else: self.gride_lines_number = m for i in range( self.gride_lines_number + 2): qp = QPainterPath() #mainlog.debug("self.rounded_step_size = {}, self.maxi={}".format(self.rounded_step_size, self.maxi)) y = y_base - self.rounded_step_size * i * self.y_factor qp.moveTo(0,y) # A bit of shuffle on y for visual effect qp.lineTo(width,y + (i % 3) - 1) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(QColor(0, 0, 25)) # alpha=255=fully opaque pen.setWidth(5) painter.setPen(pen) painter.drawPath(qp) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(QColor(30, 30, 30)) # alpha=255=fully opaque pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp) def _draw_y_axis(self,painter, y_base, width, height, steps): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque text_pen.setWidth(1) painter.setPen(text_pen) if self.rounded_step_size < 1: fmt = "{:.1f}" else: fmt = "{:.0f}" if self.rounded_step_size > 0: for i in range(int(self.maxi / self.rounded_step_size) + 1): y = y_base - self.rounded_step_size * i * self.y_factor painter.drawText(self.margin,y, fmt.format(self.rounded_step_size * i)) def draw_title(self, painter): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(255, 255, 255)) # alpha=255=fully opaque text_pen.setWidth(1) painter.setPen(text_pen) painter.setFont(self.title_font) r = QRect(self.margin,0,self.width() - 2*self.margin,self.height()) painter.drawText(r, Qt.AlignLeft + Qt.TextWordWrap, self.title) def draw_no_data(self, painter): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(128, 128, 128)) # alpha=255=fully opaque text_pen.setWidth(1) painter.setPen(text_pen) painter.setFont(self.title_font) r = QRect( self.margin, 0, self.width() - 2*self.margin, self.height()) painter.drawText(r, (Qt.AlignCenter | Qt.AlignLeft) + Qt.TextWordWrap, _("No data")) def paintEvent(self,event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing) base_font = painter.font() self._compute_lengths(painter) if self.no_draw: self.draw_title(painter) self.draw_no_data(painter) return self._draw_grid(painter, self.y_base, self.width(), self.total_height, 6) # self._draw_over_grid(painter) self._draw_legend2(painter, self.legends) self._draw_x_axis(painter, self.x_legends) self._draw_y_axis(painter, self.y_base, self.width(), self.total_height, 6) self.draw_title(painter) painter.setFont(base_font) if self.data: for i in range(len(self.data)): self._draw_serie(painter, i, self.graph_colors[i % len(self.graph_colors)]) if self._horizontal_ruler_y_value != None: self._draw_horizontal_ruler(painter, self._horizontal_ruler_text, self._horizontal_ruler_y_value, self._horizontal_ruler_color) self._draw_selected_items_in_series(painter) # def compute_mini_maxi(self, delta_min): # if self.data: # mini = 99999999999 # maxi = 0 # for l in self.data: # if l: # mini = min(min(l),mini) # maxi = max(max(l),maxi) # # if maxi - mini < delta_min: # # mainlog.debug("* "*20 + str(delta_min) ) # maxi = mini + delta_min # # self.mini, self.maxi = mini, maxi # # assert 0 <= self.mini <= self.maxi, "0 <= {} <= {}".format(self.mini, self.maxi) def set_mini_maxi(self,mini,maxi): """ Set mini/maxi Y values. That's useful to have, for example, the 0 value on the graph. If mini and maxi are None, the their value will be guessed from the data drawn. :param mini: Minimum value that will be displayed on the Y axis :param maxi: Maximum value that will be displayed on the Y axis :return: """ assert (mini == None and maxi == None) or (0 <= mini <= maxi), "0 <= {} <= {}".format( mini, maxi) self.forced_maxi = maxi self.forced_mini = mini def set_horizontal_ruler(self, text, y_value, color = Qt.GlobalColor.green): self._horizontal_ruler_text = text self._horizontal_ruler_y_value = y_value self._horizontal_ruler_color = color def _draw_box_under_text(self,painter,x,y,text): r = QRect(1,1,1000,1000) bb = painter.boundingRect(r,Qt.AlignLeft,text) bb = QRect(x,y - bb.height() +2 , bb.width() + 2, bb.height()) # print("{} {} {} {}".format(bb.x(),bb.y(),bb.width(),bb.height())) fill_color = QColor(0,0,0) fill_color.setAlpha(170) brush = QBrush(fill_color) painter.fillRect(bb,brush) def _draw_horizontal_ruler(self, painter, text, y_value, color): y = y_value * self.y_factor pen = QPen() pen.setCapStyle(Qt.SquareCap) pen.setColor(color) qp = QPainterPath() r = QRect(1,1,1000,1000) bb = painter.boundingRect(r,Qt.AlignLeft,text) bb = QRect(self.x_base,self.y_base - y - bb.height(), bb.width() + 2, bb.height()) # print("{} {} {} {}".format(bb.x(),bb.y(),bb.width(),bb.height())) fill_color = QColor(0,0,0) fill_color.setAlpha(128) brush = QBrush(fill_color) painter.fillRect(bb,brush) qp.moveTo(self.x_base,self.y_base - y) qp.lineTo(self.total_width + self.x_base, self.y_base - y) painter.setPen(pen) painter.drawPath(qp) text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(color) # alpha=255=fully opaque text_pen.setWidth(1) painter.setPen(text_pen) painter.drawText(self.x_base,self.y_base - y - 5,text)
def _draw_legend(self, painter, labels): text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque text_pen.setWidth(1) highlighted_text_pen = QPen() highlighted_text_pen.setColor(QColor(255, 255, 255)) # alpha=255=fully opaque highlighted_text_pen.setWidth(1) line_pen = QPen() line_pen.setCapStyle(Qt.RoundCap) line_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque line_pen.setWidth(2) max_width = 0 fm = painter.fontMetrics() for label in labels: max_width = max(fm.boundingRect(label).width(), max_width) y_room = int(self.height() * 0.5 / self.text_height) nb_columns = int( len(labels) / y_room) if len(labels) % y_room > 0: nb_columns += 1 y_room = y_room * self.text_height x = self.margin + self.total_width - nb_columns * (max_width + 10) # 100 / 20 = 5 entry per column # 17 / 5 = 3 => 4 columns # print self.height() * 0.5, " ", len(labels), " ", nb_columns, " y_room:", y_room y = 0 i = 0 y_offset = self.yoffset self.legend_labels_bounding_boxes = [] # Draw a background rectanlge behin the legend fill_color = QColor(16,16,48) fill_color.setAlpha(196) brush = QBrush(fill_color) h = y_room w = nb_columns * (max_width + 10) if nb_columns == 1: h = len(labels) * self.text_height r = QRect(x-3, y_offset - self.text_height , w, h + 6) painter.fillRect(r,brush) sorted_labels = sorted( zip( range(len(labels)), labels, map(id,self.data)), lambda a,b:cmp(a[1],b[1])) # mainlog.debug( sorted_labels) # We sort labels on their names (but keep the indices right) for data_ndx, label in sorted( zip(range(len(labels)),labels), lambda a,b:cmp(a[1],b[1])): # Draw coloured line line_pen.setColor(self.graph_colors[data_ndx % len(self.graph_colors)]) # alpha=255=fully opaque painter.setPen(line_pen) if data_ndx == self.ndx_best_serie: r = QRect(x-3, y_offset+ y-self.text_height+3, max_width + 6, self.text_height) painter.drawRect(r) painter.setPen(highlighted_text_pen) else: painter.drawLine(x,y_offset+y+3,x+max_width,y_offset+y + 3) painter.setPen(text_pen) painter.drawText(x,y_offset+y,label) # Remember text bounding box r = QRect(x,y_offset+y - self.text_height,max_width,self.text_height) # if label == "TO": # painter.drawRect(r) bb = painter.boundingRect(r,Qt.AlignLeft,label) # bb.adjust(-5,-5,+5,+5) # print label,label_ndx,r.x(), r.y(), r.width(), r.height() self.legend_labels_bounding_boxes.append( (data_ndx,bb) ) if y >= y_room - self.text_height: y = 0 x += max_width + 10 else: y += self.text_height i += 1
class parametricPulseGraph(QGraphicsItem): COLOR_MAP = {} SPEED_LIMIT = 0.25 # we can only step through a quarter of the data at a time SLICE_PROPORTION = 0.1 UNSLICED_THICKNESS = 3 UNSLICED_OPACITY = 0.25 SLICED_THICKNESS = 6 SLICED_OPACITY = 0.75 FULL_SIZE = 400 SMALL_SIZE = 100 LABEL_THRESHOLD = 150 LABEL_FONT = QFont('Gill Sans',18) LABEL_FONT.setStyleHint(QFont.StyleHint.SansSerif) LABEL_PEN = QPen(Qt.black) LABEL_OPACITY = 0.75 LABEL_PADDING = 10 TEXT_FONT = QFont('Gill Sans', 14) TEXT_FONT.setStyleHint(QFont.StyleHint.SansSerif) TEXT_PEN = QPen(Qt.white) TEXT_OPACITY = 0.75 BORDER_WIDTH = 2.0 BORDER = QPen(Qt.black,BORDER_WIDTH) BACKGROUND = QBrush(Qt.black) BACKGROUND_OPACITY = 0.9 def __init__(self, parent, xAttribute, yAttribute, vectors=None): QGraphicsItem.__init__(self) self.parent = parent self.xAttribute = xAttribute self.yAttribute = yAttribute self.vectors = vectors self.xmin = None self.xmax = None self.ymin = None self.ymax = None self.isTop = False self.isLeft = False self.isRight = False self.isBottom = False self.width = parametricPulseGraph.FULL_SIZE self.height = parametricPulseGraph.FULL_SIZE if self.vectors == None: return for vlist in self.vectors.itervalues(): for x0,y0,t0,x1,y1,t1 in vlist: if self.xmin == None: self.xmin = min(x0,x1) self.xmax = max(x0,x1) self.ymin = min(y0,y1) self.ymax = max(y0,y1) else: self.xmin = min(self.xmin,x0,x1) self.xmax = max(self.xmax,x0,x1) self.ymin = min(self.ymin,y0,y1) self.ymax = max(self.ymax,y0,y1) if self.xmin == None or self.xmax == None or self.ymin == None or self.ymax == None: self.xmin = None self.xmax = None self.ymin = None self.ymax = None self.vectors = None def paint(self, painter, option, widget=None): normalRect = QRectF(0,0,self.width,self.height) rotatedRect = QRectF(0,-self.height,self.width,self.height) if self.isTop or self.isLeft or self.isRight or self.isBottom: painter.setFont(parametricPulseGraph.LABEL_FONT) painter.setPen(parametricPulseGraph.LABEL_PEN) painter.setOpacity(parametricPulseGraph.LABEL_OPACITY) if self.isTop: labelRect = QRectF(-self.height,-self.width,self.height-parametricPulseGraph.LABEL_PADDING,self.width) painter.rotate(90) painter.drawText(labelRect, Qt.AlignRight | Qt.AlignVCenter, self.xAttribute) painter.rotate(-90) if self.isBottom: labelRect = QRectF(self.height+parametricPulseGraph.LABEL_PADDING,-self.width,self.height,self.width) painter.rotate(90) painter.drawText(labelRect, Qt.AlignLeft | Qt.AlignVCenter, self.xAttribute) painter.rotate(-90) if self.isLeft: labelRect = QRectF(-self.width,0,self.width-parametricPulseGraph.LABEL_PADDING,self.height) painter.drawText(labelRect, Qt.AlignRight | Qt.AlignVCenter, self.yAttribute) if self.isRight: labelRect = QRectF(self.width+parametricPulseGraph.LABEL_PADDING,0,self.width,self.height) painter.drawText(labelRect, Qt.AlignLeft | Qt.AlignVCenter, self.yAttribute) painter.setPen(parametricPulseGraph.BORDER) painter.setOpacity(parametricPulseGraph.BACKGROUND_OPACITY) painter.drawRect(normalRect) painter.fillRect(normalRect,parametricPulseGraph.BACKGROUND) if self.vectors != None and (self.xmax != self.xmin or self.ymax != self.ymin): # Draw vectors for cat,color in parametricPulseGraph.COLOR_MAP.iteritems(): if not self.vectors.has_key(cat): continue if self.xmax == self.xmin: xScale = None else: xScale = self.width / (self.xmax-self.xmin) if self.ymax == self.ymin: yScale = None else: yScale = self.height / (self.ymax-self.ymin) for x0,y0,t0,x1,y1,t1 in self.vectors[cat]: if xScale == None: x0 = self.width/2 x1 = self.width/2 else: x0 = (x0-self.xmin)*xScale x1 = (x1-self.xmin)*xScale if yScale == None: y0 = self.height/2 y1 = self.height/2 else: y0 = (y0-self.ymin)*yScale y1 = (y1-self.ymin)*yScale painter.setOpacity(parametricPulseGraph.UNSLICED_OPACITY) painter.setPen(QPen(color,parametricPulseGraph.UNSLICED_THICKNESS)) painter.drawLine(x0,y0,x1,y1) if t0 == None or t1 == None: return startTime = max(parametricPulseGraph.CURRENT_TIME-parametricPulseGraph.SLICE_DURATION,t0) endTime = min(parametricPulseGraph.CURRENT_TIME+parametricPulseGraph.SLICE_DURATION,t1) if not endTime <= startTime: startTime = (startTime-t0)/(t1-t0) endTime = (endTime-t0)/(t1-t0) xstart = (x1-x0)*startTime xend = (x1-x0)*endTime ystart = (y1-y0)*startTime yend = (y1-y0)*endTime painter.setOpacity(parametricPulseGraph.SLICED_OPACITY) painter.setPen(QPen(color,parametricPulseGraph.SLICED_THICKNESS)) painter.drawLine(x0+xstart,y0+ystart,x0+xend,y0+yend) # Draw labels if min(self.width,self.height) >= parametricPulseGraph.LABEL_THRESHOLD: painter.setFont(parametricPulseGraph.TEXT_FONT) painter.setPen(parametricPulseGraph.TEXT_PEN) painter.setOpacity(parametricPulseGraph.TEXT_OPACITY) painter.drawText(normalRect,Qt.AlignHCenter | Qt.AlignTop, "%s, %f" % (self.yAttribute,self.ymax)) painter.drawText(normalRect,Qt.AlignHCenter | Qt.AlignBottom, "%s, %f" % (self.yAttribute,self.ymin)) painter.rotate(90) painter.drawText(rotatedRect,Qt.AlignHCenter | Qt.AlignTop, "%s, %f" % (self.xAttribute,self.xmax)) painter.drawText(rotatedRect,Qt.AlignHCenter | Qt.AlignBottom, "%s, %f" % (self.xAttribute,self.xmin)) else: painter.setFont(parametricPulseGraph.TEXT_FONT) painter.setPen(parametricPulseGraph.TEXT_PEN) painter.setOpacity(parametricPulseGraph.TEXT_OPACITY) if self.vectors == None: painter.drawText(normalRect,Qt.AlignHCenter | Qt.AlignVCenter, "No Data") else: painter.drawText(normalRect,Qt.AlignHCenter | Qt.AlignVCenter, "No Variation") def boundingRect(self): pensize = parametricPulseGraph.BORDER_WIDTH/2 return QRectF(-pensize,-pensize,self.width+pensize,self.height+pensize) def mousePressEvent(self, event): self.parent.setTarget(self.xAttribute,self.yAttribute) @staticmethod def nextFrame(): parametricPulseGraph.CURRENT_TIME += parametricPulseGraph.CURRENT_SPEED if parametricPulseGraph.CURRENT_TIME - parametricPulseGraph.SLICE_DURATION > parametricPulseGraph.TIME_END: parametricPulseGraph.CURRENT_TIME = parametricPulseGraph.TIME_START - parametricPulseGraph.SLICE_DURATION @staticmethod def updateTimes(start,end): # These values will change parametricPulseGraph.TIME_START = int(start) parametricPulseGraph.TIME_END = math.ceil(end) parametricPulseGraph.CURRENT_TIME = int(parametricPulseGraph.TIME_START + (parametricPulseGraph.TIME_END-parametricPulseGraph.TIME_START)*0.5) parametricPulseGraph.SLICE_DURATION = math.ceil((parametricPulseGraph.TIME_END-parametricPulseGraph.TIME_START)*parametricPulseGraph.SLICE_PROPORTION) # really number of seconds before and after parametricPulseGraph.MIN_SPEED = 0 parametricPulseGraph.MAX_SPEED = math.ceil((parametricPulseGraph.TIME_END-parametricPulseGraph.TIME_START)*parametricPulseGraph.SPEED_LIMIT) parametricPulseGraph.CURRENT_SPEED = math.ceil(parametricPulseGraph.MAX_SPEED*0.25) # everything is moved forward this many seconds every frame (THAT speed is defined by Viz.FRAME_DURATION)
def _draw_grid(self,painter, y_base, width, height, steps): m = int(self.maxi / self.rounded_step_size) if self.timer.isActive(): self.gride_lines_number = self.timer_ticks if self.gride_lines_number >= m: self.timer.stop() else: self.gride_lines_number = m for i in range( self.gride_lines_number + 2): qp = QPainterPath() #mainlog.debug("self.rounded_step_size = {}, self.maxi={}".format(self.rounded_step_size, self.maxi)) y = y_base - self.rounded_step_size * i * self.y_factor qp.moveTo(0,y) # A bit of shuffle on y for visual effect qp.lineTo(width,y + (i % 3) - 1) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(QColor(0, 0, 25)) # alpha=255=fully opaque pen.setWidth(5) painter.setPen(pen) painter.drawPath(qp) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(QColor(30, 30, 30)) # alpha=255=fully opaque pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp)
def __init__(self): super(PosterViewDelegate, self).__init__() self.backgoundBrush = QBrush(QColor("#111")) self.selectedBrush = QBrush(QColor(255, 255, 255, 50)) self.outline = QPen(QColor("#999"))
class CustomLabel(qg.QLabel): _glowPens = {} for index in range(1, 11): _glowPens[index] = [ QPen(QColor(0, 255, 0, 12 * index), 1, qc.Qt.SolidLine), QPen(QColor(0, 255, 0, 5 * index), 1, qc.Qt.SolidLine), QPen(QColor(0, 255, 0, 2 * index), 1, qc.Qt.SolidLine), QPen(QColor(125, 200, 100), 1, qc.Qt.SolidLine) ] _pen_text = QPen(QColor(200, 200, 200), 1, qc.Qt.SolidLine) _pen_Shadow = QPen(QColor(9, 10, 12), 1, qc.Qt.SolidLine) _pen_border = QPen(QColor(9, 10, 12), 2, qc.Qt.SolidLine) _pen_clear = QPen(QColor(0, 0, 0, 0), 1, qc.Qt.SolidLine) _penText_disable = QPen(QColor(102, 107, 110), 1, qc.Qt.SolidLine) _penShadow_disable = QPen(QColor(0, 0, 0), 1, qc.Qt.SolidLine) _brushClear = QBrush(QColor(0, 0, 0, 0)) _brushBorder = QBrush(QColor(9, 10, 12)) glow_index = 0 def __init__(self, *args, **kwargs): qg.QLabel.__init__(self, *args, **kwargs) font = qg.QFont() font.setPointSize(10) font.setFamily('Helvetic') self.setFont(font) self.setMargin(2) self._glow_index = 0 def setGlowValue(self, value): self._glow_index = min(max(value / 10, 0), 10) utils.executeDeferred(self.update) def paintEvent(self, event): painter = qg.QPainter(self) option = qg.QStyleOption() option.initFrom(self) x = option.rect.x() y = option.rect.y() height = option.rect.height() - 1 width = option.rect.width() - 1 painter.setRenderHint(qg.QPainter.Antialiasing) painter.setRenderHint(qg.QPainter.TextAntialiasing) alignment = (qc.Qt.AlignHCenter | qc.Qt.AlignVCenter) text = self.text() if text == '': return font = self.font() font_metrics = qg.QFontMetrics(font) text_width = font_metrics.width(text) text_height = font.pointSize() textPath = qg.QPainterPath() textPath.addText((width - text_width) / 2, height - ((height - text_height) / 2), font, text) if self.isEnabled(): pens_text = self._pen_text pens_shadow = self._pen_Shadow else: pens_text = self._penText_disable pens_shadow = self._penShadow_disable painter.setPen(pens_shadow) painter.drawPath(textPath) painter.setPen(pens_text) painter.drawText(x, y, width, height, alignment, text) glow_index = self._glow_index glow_pens = self._glowPens if glow_index > 0: for index in range(3): painter.setPen(glow_pens[glow_index - (glow_index / 2)][index]) painter.drawPath(textPath) painter.setPen(glow_pens[glow_index][3]) painter.drawText(x, y, width, height, alignment, text)
class SelectBox(QRubberBand): """ Subclass of `QRubberBand`_ TOWRITE """ def __init__(self, s, parent=None): """ Default class constructor. :param `s`: TOWRITE :type `s`: QRubberBand.Shape :param `parent`: Pointer to a parent widget instance. :type `parent`: `QWidget`_ """ super(SelectBox, self).__init__(s, parent) # private self._leftBrushColor = QColor() self._rightBrushColor = QColor() self._leftPenColor = QColor() self._rightPenColor = QColor() self._alpha = 255 # quint8 #: TODO: what is the initial int? self._dirBrush = QBrush() self._leftBrush = QBrush() self._rightBrush = QBrush() self._dirPen = QPen() self._leftPen = QPen() self._rightPen = QPen() self._boxDir = False #: TODO: is this initial bool value right? # Default values self.setColors(QColor(Qt.darkGreen), QColor(Qt.green), QColor(Qt.darkBlue), QColor(Qt.blue), 32) def paintEvent(self, event): """ Handles the ``paintEvent`` event for :class:`SelectBox`. :param `event`: A `QPaintEvent`_ to be processed. """ painter = QPainter(self) painter.setPen(self._dirPen) width, height = self.width(), self.height() painter.fillRect(0, 0, width - 1, height - 1, self._dirBrush) painter.drawRect(0, 0, width - 1, height - 1) def forceRepaint(self): """ Force repaint the rubberband. .. NOTE:: HACK: Take that QRubberBand! """ # HACK: Take that QRubberBand! hack = self.size() # QSize self.resize(hack + QSize(1, 1)) self.resize(hack) # Slots ------------------------------------------------------------------ @Slot(int) def setDirection(self, dir): """ TOWRITE :param `dir`: TOWRITE :type `dir`: int """ if not dir: self._dirPen = self._leftPen self._dirBrush = self._leftBrush else: self._dirPen = self._rightPen self._dirBrush = self._rightBrush self._boxDir = dir @Slot(QColor, QColor, QColor, QColor, int) def setColors(self, colorL, fillL, colorR, fillR, newAlpha): """ TOWRITE :param `colorL`: TOWRITE :type `colorL`: `QColor`_ :param `fillL`: TOWRITE :type `fillL`: `QColor`_ :param `colorR`: TOWRITE :type `colorR`: `QColor`_ :param `fillR`: TOWRITE :type `fillR`: `QColor`_ :param `newAlpha`: TOWRITE :type `newAlpha`: int """ qDebug("SelectBox setColors()") self._alpha = newAlpha self._leftPenColor = colorL # TODO: allow customization self._leftBrushColor = QColor(fillL.red(), fillL.green(), fillL.blue(), self._alpha) self._rightPenColor = colorR # TODO: allow customization self._rightBrushColor = QColor(fillR.red(), fillR.green(), fillR.blue(), self._alpha) self._leftPen.setColor(self._leftPenColor) self._leftPen.setStyle(Qt.DashLine) self._leftBrush.setStyle(Qt.SolidPattern) self._leftBrush.setColor(self._leftBrushColor) self._rightPen.setColor(self._rightPenColor) self._rightPen.setStyle(Qt.SolidLine) self._rightBrush.setStyle(Qt.SolidPattern) self._rightBrush.setColor(self._rightBrushColor) if not self._boxDir: self._dirPen = self._leftPen self._dirBrush = self._leftBrush else: self._dirPen = self._rightPen self._dirBrush = self._rightBrush self.forceRepaint()
class DT_Slider(QtGui.QSlider, base.Base): _glow_brushes = {} for index in range(1, 11): _glow_brushes[index] = [ QBrush(QColor(0, 255, 0, 1 * index)), QBrush(QColor(0, 255, 0, 3 * index)), QBrush(QColor(0, 255, 0, 8 * index)), QBrush(QColor(0, 255, 0, 25.5 * index)), QBrush(QColor(0, 255, 0, 15 * index)), ] _pens_dark = QPen(QColor(0, 5, 9), 1, QtCore.Qt.SolidLine) _pens_light = QPen(QColor(16, 17, 19), 1, QtCore.Qt.SolidLine) _gradient_inner = QLinearGradient(0, 9, 0, 15) _gradient_inner.setColorAt(0, QColor(69, 73, 76)) _gradient_inner.setColorAt(1, QColor(17, 18, 20)) _gradient_outer = QLinearGradient(0, 9, 0, 15) _gradient_outer.setColorAt(0, QColor(53, 57, 60)) _gradient_outer.setColorAt(1, QColor(33, 34, 36)) def __init__(self, *args, **kwargs): QtGui.QSlider.__init__(self, *args, **kwargs) self._hover = False self._glow_index = 0 self._anim_timer = QtCore.QTimer() self._anim_timer.timeout.connect(self._animateGlow) self.setOrientation(QtCore.Qt.Horizontal) self.setFixedHeight(22) self.setMinimumWidth(50) self._track = False self._tracking_point = {} self._anim_follow_timer = QtCore.QTimer() self._anim_follow_timer.timeout.connect(self._removeTrackingPoints) self.valueChanged.connect(self._trackChanges) self._updateTracking() def setRange(self, *args, **kwargs): QtGui.QSlider.setRange(self, *args, **kwargs) self._updateTracking() def setMinimum(self, *args, **kwargs): QtGui.QSlider.setMinimum(self, *args, **kwargs) self._updateTracking() def setMaximum(self, *args, **kwargs): QtGui.QSlider.setMaximum(self, *args, **kwargs) self._updateTracking() def _updateTracking(self): self._tracking_points = [0 ] * (abs(self.maximum() - self.minimum()) + 1) def setValue(self, *args, **kwargs): QtGui.QSlider.setValue(self, *args, **kwargs) for index in range(len(self._tracking_points)): self._tracking_points[index] = 0 def mouseMoveEvent(self, event): QtGui.QSlider.mouseMoveEvent(self, event) if self._anim_follow_timer.isActive(): return self._anim_follow_timer.start(30) def _trackChanges(self, value): value = value - self.minimum() self._tracking_points[value] = 10 def _removeTrackingPoints(self): self._track = False for index, value in enumerate(self._tracking_points): if value > 0: self._tracking_points[index] -= 1 self._track = True if self._track is False: self._anim_follow_timer.stop() utils.executeDeferred(self.update) def paintEvent(self, event): painter = QtGui.QStylePainter(self) option = QtGui.QStyleOption() option.initFrom(self) x = option.rect.x() y = option.rect.y() width = option.rect.width() - 1 height = option.rect.height() - 1 orientation = self.orientation() painter.setRenderHint(QtGui.QPainter.Antialiasing) painter.setPen(self._pens_shadow) painter.setBrush(self._brush_border) painter.drawRoundedRect( QtCore.QRect(x + 1, y + 1, width - 1, height - 1), 10, 10) mid_height = (height / 2) + 1 painter.setPen(self._pens_dark) painter.drawLine(10, mid_height, width - 8, mid_height) painter.setRenderHint(QtGui.QPainter.Antialiasing, False) painter.setPen(self._pens_light) painter.drawLine(10, mid_height, width - 10, mid_height) painter.setRenderHint(QtGui.QPainter.Antialiasing, True) minimum = self.minimum() maximum = self.maximum() value_range = maximum - minimum value = self.value() - minimum increment = ((width - 20) / float(value_range)) center = 10 + (increment * value) center_point = QtCore.QPoint(x + center, y + mid_height) painter.setPen(self._pens_clear) glow_index = self._glow_index glow_brushes = self._glow_brushes if self._track is True: for index, track_value in enumerate(self._tracking_points): if track_value == 0: continue track_center = 10 + (increment * index) painter.setBrush(glow_brushes[track_value][4]) painter.drawEllipse(QtCore.QPoint(track_center, mid_height), 7, 7) if glow_index > 0: for index, size in zip(range(4), range(10, 6, -1)): painter.setBrush(glow_brushes[glow_index][index]) painter.drawEllipse(center_point, size, size) painter.setBrush(QtGui.QBrush(self._gradient_outer)) painter.drawEllipse(center_point, 6, 6) painter.setBrush(QtGui.QBrush(self._gradient_inner)) painter.drawEllipse(center_point, 5, 5) def enterEvent(self, event): if not self.isEnabled(): return self._hover = True self._startAnim() def leaveEvent(self, event): if not self.isEnabled(): return self._hover = False self._startAnim()
def _draw_serie(self, painter, ndx_serie, color): last_item = len(self.data) - 1 serie = self.data[ndx_serie] serie_below = [0] * len(self.data[last_item]) if ndx_serie < len(self.data) - 1: serie_below = self.data[ndx_serie + 1] fill_color = QColor(color) fill_color.setAlpha(64) brush = QBrush(fill_color) pen = QPen() pen.setCapStyle(Qt.SquareCap) pen.setColor(color) for i in range(len(serie)): x, y_top, y_below = self._item_coordinates(ndx_serie, i) qp = QPainterPath() h = float(y_top - y_below - 1) if h > 0: qp.addRect(x, float(self.y_base - y_top), float(self.bar_width), h) painter.fillPath(qp, brush) if self.ndx_best_serie == ndx_serie and ( self.best_serie_intra_ndx is None or (self.best_serie_intra_ndx >= 0 and self.best_serie_intra_ndx == i)): pen.setWidth(3) else: pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp) if ndx_serie == self.ndx_best_serie: fm = painter.fontMetrics() pen.setWidth(1) painter.setPen(pen) serie_below = None if ndx_serie < len(self.data) - 1: serie_below = self.data[ndx_serie + 1] for i in range(len(serie)): if (self.best_serie_intra_ndx == i) or self.best_serie_intra_ndx is None: x, y_top, y_below = self._item_coordinates(ndx_serie, i) l_len = 15 v = serie[i] if serie_below: v = v - serie_below[i] v = str(int(v)) bb = fm.boundingRect(v) pen.setColor(color) y = 0 if i < len(serie) - 1: # small diagonal going top, right painter.drawLine(x + self.bar_width, self.y_base - y_top, x + self.bar_width + l_len, self.y_base - (y_top + l_len)) x = x + self.bar_width + l_len y = y_top + l_len else: # small diagonal going top, left painter.drawLine(x, self.y_base - y_top, x - l_len, self.y_base - (y_top - l_len)) x = x - l_len - bb.width() y = y_top - l_len bb.moveTo(int(x), int(self.y_base - y - bb.height())) brush = QBrush(Qt.GlobalColor.red) bb.adjust(-2, +2, +4, +4) bb.adjust(-2, -2, +2, +2) painter.fillRect(bb, brush) bb.adjust(+2, +2, -2, -2) painter.drawRect(bb) pen.setColor(Qt.GlobalColor.white) painter.setPen(pen) painter.drawText(x, self.y_base - y, str(int(v)))
def paint(self, painter, option, widget): painter.setPen(QPen(Qt.black, 1)) painter.drawRect(self.getRect())
class CustomLineEdit(qg.QLineEdit): _glowPens = {} for index in range(1, 11): _glowPens[index] = [ QPen(QColor(0, 255, 0, 12 * index), 1, qc.Qt.SolidLine), QPen(QColor(0, 255, 0, 5 * index), 1, qc.Qt.SolidLine), QPen(QColor(0, 255, 0, 2 * index), 1, qc.Qt.SolidLine), QPen(QColor(125, 200, 100), 1, qc.Qt.SolidLine) ] _pen_text = QPen(QColor(200, 200, 200), 1, qc.Qt.SolidLine) _pen_Shadow = QPen(QColor(9, 10, 12), 1, qc.Qt.SolidLine) _pen_border = QPen(QColor(9, 10, 12), 2, qc.Qt.SolidLine) _pen_clear = QPen(QColor(0, 0, 0, 0), 1, qc.Qt.SolidLine) _penText_disable = QPen(QColor(100, 100, 100), 1, qc.Qt.SolidLine) _penShadow_disable = QPen(QColor(0, 0, 0), 1, qc.Qt.SolidLine) _brushClear = QBrush(QColor(0, 0, 0, 0)) _brushBorder = QBrush(QColor(9, 10, 12)) #---------------------------------------------------------------------------------------------------------------------------# def __init__(self, *args, **kwargs): qg.QLineEdit.__init__(self, *args, **kwargs) font = qg.QFont() font.setPixelSize(16) self.setFont(font) font.setFamily('Helvetic') self.font_metrics = qg.QFontMetrics(font) self.setFixedHeight(self.font_metrics.height() + 5) self._placeholder_message = '' self._text_glow = {} self._previous_text = '' text = self.text() if text: self.setText(text) self._animTimer = qc.QTimer() self._animTimer.timeout.connect(self._animateText) #---------------------------------------------------------------------------------------------------------------------------# def setText(self, *args): qg.QLineEdit.setText(self, *args) self._text_glow = {} for index in range(len(text)): self._text_glow[index] = 0 def setPlaceholderMessage(self, text): self._placeholder_message = str(text) #---------------------------------------------------------------------------------------------------------------------------# def _animateText(self): stop_animating = True for key, value in self._text_glow.items(): if value > 0: stop_animating = False self._text_glow[key] = value - 1 if stop_animating: self._animTimer.stop() #print self._text_glow utils.executeDeferred(self.update) #---------------------------------------------------------------------------------------------------------------------------# def keyPressEvent(self, *args): qg.QLineEdit.keyPressEvent(self, *args) text = self.text() if text == self._previous_text: return len_text = len(text) if len_text > len(self._previous_text): self._animTimer.start(20) self._text_glow[len_text - 1] = 0 self._text_glow[self.cursorPosition() - 1] = 10 elif len(self._text_glow.keys()) == 0: self._animTimer.stop() self._previous_text = text #print self._text_glow #---------------------------------------------------------------------------------------------------------------------------# def paintEvent(self, event): painter = qg.QStylePainter(self) option = qg.QStyleOptionFrame() self.initStyleOption(option) painter.setRenderHint(qg.QPainter.Antialiasing) painter.setRenderHint(qg.QPainter.TextAntialiasing) contents = self.style().subElementRect(qg.QStyle.SE_LineEditContents, option, self) contents.setLeft(contents.left() + 2) contents.setRight(contents.right() - 2) alignment = (qc.Qt.AlignLeft | qc.Qt.AlignVCenter) text = self.text() font = self.font() fontMetrics = self.font_metrics if not text: painter.setPen(self._penText_disable) painter.drawText(contents, alignment, self._placeholder_message) selected = self.hasSelectedText() if selected: selection = self.selectedText() selection_start = self.selectionStart() selection_end = selection_start + len(selection) left_edge = contents.left() for index, letter in enumerate(text): text_width = fontMetrics.width(text[0:index]) contents.setLeft(left_edge + text_width) x, y, width, height = contents.getRect() painter.setPen(self._pen_Shadow) painter.drawText(x + 1, y + 1, width, height, alignment, letter) painter.setPen(self._pen_text) painter.drawText(contents, alignment, letter) glow_index = self._text_glow[index] if selected and (index >= selection_start and index < selection_end): glow_index = 10 if glow_index > 0: text_path = qg.QPainterPath() text_path.addText(contents.left(), font.pixelSize() + 2, font, letter) for index in range(3): painter.setPen(self._glowPens[glow_index][index]) painter.drawPath(text_path) painter.setPen(self._glowPens[glow_index][3]) painter.drawText(contents, alignment, letter) if not self.hasFocus(): return contents.setLeft(left_edge) x, y, width, height = contents.getRect() painter.setPen(self._pen_text) cursor_pos = self.cursorPosition() text_width = fontMetrics.width(text[0:cursor_pos]) pos = x + text_width top = y + 1 bottom = y + height - 1 painter.drawLine(pos, top, pos, bottom) try: cursor_glow = self._text_glow[cursor_pos - 1] except KeyError: return if cursor_glow > 0: for index in range(4): painter.setPen(self._glowPens[cursor_glow][index]) painter.drawLine(pos, top, pos, bottom)
class Base(object): _glow_pens = {} for index in range(1,11): _glow_pens[index] = [QPen(QColor(0 , 255 , 0 , 12 * index) , 1 , QtCore.Qt.SolidLine), QPen(QColor(0 , 255 , 0 , 5 * index) , 3 , QtCore.Qt.SolidLine), QPen(QColor(0 , 255 , 0 , 2 * index) , 5 , QtCore.Qt.SolidLine), QPen(QColor(0 , 255 , 0 , 25.5 * index) , 1 , QtCore.Qt.SolidLine)] _pens_text = QPen(QColor(207 , 207 , 210) , 1 , QtCore.Qt.SolidLine) _pens_shadow = QPen(QColor( 9 , 10 , 12) , 1 , QtCore.Qt.SolidLine) _pens_border = QPen(QColor( 9 , 10 , 12) , 2 , QtCore.Qt.SolidLine) _pens_clear = QPen(QColor( 0 , 0 , 0 , 0) , 1 , QtCore.Qt.SolidLine) _pens_text_disabled = QPen(QColor(102 , 107 , 110) , 1 , QtCore.Qt.SolidLine) _pens_shadow_disabled = QPen(QColor( 0 , 0 , 0) , 1 , QtCore.Qt.SolidLine) _brush_clear = QBrush(QColor(0,0,0,0)) _brush_border = QBrush(QColor(9,10,12)) def __init__(self): font = QtGui.QFont() font.setPointSize(8) font.setFamily('Calibri') self.setFont(font) self._hover = False self._glow_index = 0 self._anim_timer = QtCore.QTimer() self._anim_timer.timeout.connect(self._animateGlow) def _animateGlow(self): if self._hover: if self._glow_index >= 10: self._glow_index = 10 self._anim_timer.stop() else: self._glow_index += 1 else: if self._glow_index <= 0: self._glow_index = 0 self._anim_timer.stop() else: self._glow_index -= 1 #.update 更新函数 utils.executeDeferred(self.update) def enterEvent(self , event): #进入事件 #print 'enter' #super(self.__class__ , self).enterEvent(event) #Enabled: 激活 if not self.isEnabled(): return self._hover = True self._startAnim() def leaveEvent(self , event): #离开事件 #print 'leave' #super(self.__class__ , self).leaveEvent(event) if not self.isEnabled(): return self._hover = False self._startAnim() def _startAnim(self): if self._anim_timer.isActive(): return self._anim_timer.start(15)
class Flat_button_green_thick_01(Square_button_blue): penTick = QPen(QColor(67, 238, 16), 4, qc.Qt.SolidLine) penborder = QPen(QColor(9, 10, 12), 6, qc.Qt.SolidLine) _glowRed = {} for index in range(1, 11): _glowRed[index] = [ QPen(QColor(61, 244, 7, 5 * index), 4, qc.Qt.SolidLine), QPen(QColor(61, 244, 7, 10 * index), 5, qc.Qt.SolidLine), QPen(QColor(61, 244, 7, 15 * index), 6, qc.Qt.SolidLine), QPen(QColor(61, 244, 7, 25.5 * index), 7, qc.Qt.SolidLine) ] _size = [250, 32] def __inin__(self, *args, **kwargs): super(Flat_button_green_thick_01, self).__init__(self, *args, **kwargs) self.setFixedSize(self._size[0], self._size[1]) def paintEvent(self, event): painter = qg.QPainter(self) option = qg.QStyleOption() option.initFrom(self) x = option.rect.x() y = option.rect.y() height = option.rect.height() - 1 width = option.rect.width() - 1 painter.setRenderHint(qg.QPainter.Antialiasing) radius = 10 offSet = 0 gradient = self._gradient[NORMAL] glowIndex = self._glow_index glowPen = self._glowPens if self.isDown(): gradient = self._gradient[DOWN] offSet = 1 painter.setBrush(self._brushBorder) painter.setPen(self._pen_border) painter.drawRoundedRect(qc.QRect(x + 1, y + 1, width - 1, height - 1), radius, radius) painter.setPen(self._pen_clear) painter.setBrush(gradient[OUTER]) painter.drawRoundedRect(qc.QRect(x + 2, y + 2, width - 3, height - 3), radius, radius) painter.setBrush(gradient[INNER]) painter.drawRoundedRect(qc.QRect(x + 3, y + 3, width - 4, height - 4), radius - 1, radius - 1) painter.setBrush(self._brushClear) line_path = qg.QPainterPath() #------------------- IK- full ----------# # offset num_x = 5 num_y = 10 ####################################### # I height = option.rect.height() width = option.rect.width() line_path.moveTo(6 + num_x, height / 2) line_path.lineTo(width - num_x - 7, height / 2) line_path.moveTo(width / 2, y + num_y) line_path.lineTo(width / 2, height - num_y) ######################################### self.penTick.setCapStyle(qc.Qt.RoundCap) self.penborder.setCapStyle(qc.Qt.RoundCap) if self.isEnabled(): painter.setPen(self.penborder) painter.drawPath(line_path) painter.setPen(self.penTick) painter.drawPath(line_path) if glowIndex > 0: for index in range(3): painter.setPen(self._pen_clear) painter.drawPath(line_path) pen = self._glowRed[glowIndex][index] pen.setCapStyle(qc.Qt.RoundCap) painter.setPen(pen) painter.drawPath(line_path)
def paint(self, painter, option, widget=None): normalRect = QRectF(0,0,self.width,self.height) rotatedRect = QRectF(0,-self.height,self.width,self.height) if self.isTop or self.isLeft or self.isRight or self.isBottom: painter.setFont(parametricPulseGraph.LABEL_FONT) painter.setPen(parametricPulseGraph.LABEL_PEN) painter.setOpacity(parametricPulseGraph.LABEL_OPACITY) if self.isTop: labelRect = QRectF(-self.height,-self.width,self.height-parametricPulseGraph.LABEL_PADDING,self.width) painter.rotate(90) painter.drawText(labelRect, Qt.AlignRight | Qt.AlignVCenter, self.xAttribute) painter.rotate(-90) if self.isBottom: labelRect = QRectF(self.height+parametricPulseGraph.LABEL_PADDING,-self.width,self.height,self.width) painter.rotate(90) painter.drawText(labelRect, Qt.AlignLeft | Qt.AlignVCenter, self.xAttribute) painter.rotate(-90) if self.isLeft: labelRect = QRectF(-self.width,0,self.width-parametricPulseGraph.LABEL_PADDING,self.height) painter.drawText(labelRect, Qt.AlignRight | Qt.AlignVCenter, self.yAttribute) if self.isRight: labelRect = QRectF(self.width+parametricPulseGraph.LABEL_PADDING,0,self.width,self.height) painter.drawText(labelRect, Qt.AlignLeft | Qt.AlignVCenter, self.yAttribute) painter.setPen(parametricPulseGraph.BORDER) painter.setOpacity(parametricPulseGraph.BACKGROUND_OPACITY) painter.drawRect(normalRect) painter.fillRect(normalRect,parametricPulseGraph.BACKGROUND) if self.vectors != None and (self.xmax != self.xmin or self.ymax != self.ymin): # Draw vectors for cat,color in parametricPulseGraph.COLOR_MAP.iteritems(): if not self.vectors.has_key(cat): continue if self.xmax == self.xmin: xScale = None else: xScale = self.width / (self.xmax-self.xmin) if self.ymax == self.ymin: yScale = None else: yScale = self.height / (self.ymax-self.ymin) for x0,y0,t0,x1,y1,t1 in self.vectors[cat]: if xScale == None: x0 = self.width/2 x1 = self.width/2 else: x0 = (x0-self.xmin)*xScale x1 = (x1-self.xmin)*xScale if yScale == None: y0 = self.height/2 y1 = self.height/2 else: y0 = (y0-self.ymin)*yScale y1 = (y1-self.ymin)*yScale painter.setOpacity(parametricPulseGraph.UNSLICED_OPACITY) painter.setPen(QPen(color,parametricPulseGraph.UNSLICED_THICKNESS)) painter.drawLine(x0,y0,x1,y1) if t0 == None or t1 == None: return startTime = max(parametricPulseGraph.CURRENT_TIME-parametricPulseGraph.SLICE_DURATION,t0) endTime = min(parametricPulseGraph.CURRENT_TIME+parametricPulseGraph.SLICE_DURATION,t1) if not endTime <= startTime: startTime = (startTime-t0)/(t1-t0) endTime = (endTime-t0)/(t1-t0) xstart = (x1-x0)*startTime xend = (x1-x0)*endTime ystart = (y1-y0)*startTime yend = (y1-y0)*endTime painter.setOpacity(parametricPulseGraph.SLICED_OPACITY) painter.setPen(QPen(color,parametricPulseGraph.SLICED_THICKNESS)) painter.drawLine(x0+xstart,y0+ystart,x0+xend,y0+yend) # Draw labels if min(self.width,self.height) >= parametricPulseGraph.LABEL_THRESHOLD: painter.setFont(parametricPulseGraph.TEXT_FONT) painter.setPen(parametricPulseGraph.TEXT_PEN) painter.setOpacity(parametricPulseGraph.TEXT_OPACITY) painter.drawText(normalRect,Qt.AlignHCenter | Qt.AlignTop, "%s, %f" % (self.yAttribute,self.ymax)) painter.drawText(normalRect,Qt.AlignHCenter | Qt.AlignBottom, "%s, %f" % (self.yAttribute,self.ymin)) painter.rotate(90) painter.drawText(rotatedRect,Qt.AlignHCenter | Qt.AlignTop, "%s, %f" % (self.xAttribute,self.xmax)) painter.drawText(rotatedRect,Qt.AlignHCenter | Qt.AlignBottom, "%s, %f" % (self.xAttribute,self.xmin)) else: painter.setFont(parametricPulseGraph.TEXT_FONT) painter.setPen(parametricPulseGraph.TEXT_PEN) painter.setOpacity(parametricPulseGraph.TEXT_OPACITY) if self.vectors == None: painter.drawText(normalRect,Qt.AlignHCenter | Qt.AlignVCenter, "No Data") else: painter.drawText(normalRect,Qt.AlignHCenter | Qt.AlignVCenter, "No Variation")
class Round_button_small_red_face(Square_button_blue): penTick = QPen(QColor(200, 20, 20), 10, qc.Qt.SolidLine) penborder = QPen(QColor(9, 10, 12), 12, qc.Qt.SolidLine) _glowRed = {} for index in range(1, 11): _glowRed[index] = [ QPen(QColor(255, 20, 20, 5 * index), 9, qc.Qt.SolidLine), QPen(QColor(255, 20, 20, 10 * index), 10, qc.Qt.SolidLine), QPen(QColor(255, 20, 20, 15 * index), 12, qc.Qt.SolidLine), QPen(QColor(255, 20, 20, 25.5 * index), 13, qc.Qt.SolidLine) ] _size = [25, 25] def __inin__(self, *args, **kwargs): super(Round_button_small_red_face, self).__init__(self, *args, **kwargs) self.setFixedSize(self._size[0], self._size[1]) def paintEvent(self, event): painter = qg.QPainter(self) option = qg.QStyleOption() option.initFrom(self) x = option.rect.x() y = option.rect.y() height = option.rect.height() - 1 width = option.rect.width() - 1 center = option.rect.center() point = qc.QPointF(center.x() + 0.6, center.y() + 0.75) painter.setRenderHint(qg.QPainter.Antialiasing) radius = self.radius offSet = 0 gradient = self._gradient[NORMAL] glowIndex = self._glow_index glowPen = self._glowPens if self.isDown(): gradient = self._gradient[DOWN] offSet = 1 painter.setPen(self._pen_border) painter.drawEllipse(x + 1, y + 1, width - 1, height - 1) painter.setPen(self._pen_clear) painter.setBrush(gradient[OUTER]) painter.drawEllipse(x + 2, y + 2, width - 3, height - 2) painter.setBrush(gradient[INNER]) painter.drawEllipse(x + 3, y + 3, width - 5, height - 4) painter.setBrush(self._brushClear) ################################################## self.penborder.setCapStyle(qc.Qt.RoundCap) self._pen_Ticktext.setCapStyle(qc.Qt.RoundCap) self._pen_TickPressed.setCapStyle(qc.Qt.RoundCap) self._pen_TickHover.setCapStyle(qc.Qt.RoundCap) painter.setPen(self.penborder) painter.drawPoint(point) painter.setPen(self._pen_Ticktext) painter.drawPoint(point) self.penTick.setCapStyle(qc.Qt.RoundCap) painter.setPen(self.penborder) painter.drawPoint(point) painter.setPen(self.penTick) painter.drawPoint(point) if glowIndex > 0: for index in range(3): painter.setPen(self._pen_clear) painter.drawPoint(point) pen = self._glowRed[glowIndex][index] pen.setCapStyle(qc.Qt.RoundCap) painter.setPen(pen) painter.drawPoint(point)
class CustomCheck(qg.QCheckBox): _glowBrushes = {} for index in range(1, 11): _glowBrushes[index] = [ QBrush(QColor(0, 255, 0, 1 * index)), QBrush(QColor(0, 255, 0, 3 * index)), QBrush(QColor(0, 255, 0, 15 * index)), QBrush(QColor(50, 200, 50, 25.5 * index)) ] _glowOffBrushes = {} for index in range(1, 11): _glowOffBrushes[index] = [ QBrush(QColor(0, 150, 0, 1 * index)), QBrush(QColor(0, 150, 0, 6 * index)), QBrush(QColor(0, 150, 0, 9 * index)), QBrush(QColor(50, 200, 50, 12 * index)) ] _disableGlowBrushes = {} for index in range(1, 11): _disableGlowBrushes[index] = [ QBrush(QColor(80, 80, 80, 1 * index)), QBrush(QColor(80, 80, 80, 5 * index)), QBrush(QColor(80, 80, 80, 15 * index)), QBrush(QColor(80, 80, 80, 25.5 * index)) ] _pen_text = QPen(QColor(200, 200, 200), 1, qc.Qt.SolidLine) _pen_Shadow = QPen(QColor(9, 10, 12), 1, qc.Qt.SolidLine) _pen_border = QPen(QColor(9, 10, 12), 2, qc.Qt.SolidLine) _pen_clear = QPen(QColor(0, 0, 0, 0), 1, qc.Qt.SolidLine) _penText_disable = QPen(QColor(102, 107, 110), 1, qc.Qt.SolidLine) _penShadow_disable = QPen(QColor(0, 0, 0), 1, qc.Qt.SolidLine) _brushClear = QBrush(QColor(0, 0, 0, 0)) _brushBorder = QBrush(QColor(9, 10, 12)) def __init__(self, *args, **kwargs): qg.QCheckBox.__init__(self, *args, **kwargs) font = qg.QFont() font.setPointSize(9) font.setFamily('Helvetic') self.setFont(font) self.hover = False self._glow_index = 0 self._anim_timer = qc.QTimer() self._anim_timer.timeout.connect(self._animateGlow) self.setFixedHeight(27) self.fontMetrics = qg.QFontMetrics(font) self.radius = 5 def _animateGlow(self): if self.hover: if self._glow_index >= 10: self._glow_index = 10 while self._glow_index > 8: self._glow_index -= 0.25 #print self._glow_index if self._glow_index == 8: self._anim_timer.stop() else: self._glow_index += 1 else: if self._glow_index <= 0: self._glow_index = 0 self._anim_timer.stop() else: self._glow_index -= 1 #print self._glow_index utils.executeDeferred(self.update) #-----------------------------------------------------------------------------------------------# def enterEvent(self, event): if not self.isEnabled(): return self.hover = True self.startAnim() def leaveEvent(self, event): if not self.isEnabled(): return self.hover = False self.startAnim() def startAnim(self): if self._anim_timer.isActive(): return self._anim_timer.start(20) #-----------------------------------------------------------------------------------------------------# def paintEvent(self, event): painter = qg.QPainter(self) option = qg.QStyleOption() option.initFrom(self) x = option.rect.x() y = option.rect.y() height = option.rect.height() - 1 width = option.rect.width() - 1 painter.setRenderHint(qg.QPainter.Antialiasing) painter.setRenderHint(qg.QPainter.TextAntialiasing) alignment = (qc.Qt.AlignHCenter | qc.Qt.AlignVCenter) glowIndex = self._glow_index text = self.text() painter.setPen(self._pen_border) painter.setBrush(self._brushBorder) rounded = painter.drawRoundedRect(qc.QRect(x + 5, y + 8, 12, 12), 5, 5) if self.isEnabled(): painter.setPen(self._pen_Shadow) painter.drawText(11, y + 2, width + 1, height + 1, alignment, text) painter.setPen(self._pen_text) painter.drawText(10, y + 1, width, height, alignment, text) else: painter.setPen(self._penShadow_disable) painter.drawText(11, y + 2, width, height, alignment, text) painter.setPen(self._penText_disable) painter.drawText(10, y + 1, width, height, alignment, text) painter.setPen(self._pen_clear) if self.isEnabled(): glowBrushes = self._glowBrushes glowOffBrush = self._glowOffBrushes else: glowBrushes = self._disableGlowBrushes if self.checkState(): for index, pos, size, corner in zip(range(4), (6, 7, 8, 9), (11, 10, 10, 8), (6, 6, 6, 6)): painter.setBrush(glowBrushes[10][index]) painter.drawRoundedRect( qc.QRect((x * pos) + 6, pos + 1, size, size), corner, corner) glowIndex = self._glow_index if glowIndex > 0: for index, pos, size, corner in zip(range(4), (6, 7, 8, 9), (10, 9, 10, 9), (6, 6, 6, 6)): painter.setBrush(glowOffBrush[glowIndex][index]) painter.drawRoundedRect( qc.QRect((x * pos) + 6, pos + 1, size, size), corner, corner)
class Round_button_orange(Square_button_blue): penTick = QPen(QColor(232, 79, 17), 3, qc.Qt.SolidLine) penborder = QPen(QColor(9, 10, 12), 4, qc.Qt.SolidLine) _glowRed = {} _size = [35, 35] for index in range(1, 11): _glowRed[index] = [ QPen(QColor(232, 79, 17, 5 * index), 3, qc.Qt.SolidLine), QPen(QColor(232, 79, 17, 10 * index), 4, qc.Qt.SolidLine), QPen(QColor(232, 79, 17, 15 * index), 5, qc.Qt.SolidLine), QPen(QColor(232, 79, 17, 25.5 * index), 6, qc.Qt.SolidLine) ] def __inin__(self, *args, **kwargs): super(Round_button_orange, self).__init__(self, *args, **kwargs) self.setFixedSize(self._size[0], self._size[1]) def paintEvent(self, event): painter = qg.QPainter(self) option = qg.QStyleOption() option.initFrom(self) x = option.rect.x() y = option.rect.y() height = option.rect.height() - 1 width = option.rect.width() - 1 painter.setRenderHint(qg.QPainter.Antialiasing) radius = self.radius offSet = 0 gradient = self._gradient[NORMAL] glowIndex = self._glow_index glowPen = self._glowPens if self.isDown(): gradient = self._gradient[DOWN] offSet = 1 painter.setPen(self._pen_border) painter.drawEllipse(x + 1, y + 1, width - 1, height - 1) painter.setPen(self._pen_clear) painter.setBrush(gradient[OUTER]) painter.drawEllipse(x + 2, y + 2, width - 3, height - 2) painter.setBrush(gradient[INNER]) painter.drawEllipse(x + 3, y + 3, width - 5, height - 4) painter.setBrush(self._brushClear) line_path = qg.QPainterPath() ################################################## # CROSSSS x_off = 8 y_off = 9 height = option.rect.height() width = option.rect.width() line_path.moveTo(x + x_off, y + (height / 2)) line_path.lineTo(width - x_off, y + (height / 2)) line_path.moveTo(width / 2, y + y_off) line_path.lineTo(width / 2, height - y_off) self.penborder.setCapStyle(qc.Qt.RoundCap) self._pen_Ticktext.setCapStyle(qc.Qt.RoundCap) self._pen_TickPressed.setCapStyle(qc.Qt.RoundCap) self._pen_TickHover.setCapStyle(qc.Qt.RoundCap) painter.setPen(self.penborder) painter.drawPath(line_path) painter.setPen(self._pen_Ticktext) painter.drawPath(line_path) self.penTick.setCapStyle(qc.Qt.RoundCap) painter.setPen(self.penborder) painter.drawPath(line_path) painter.setPen(self.penTick) painter.drawPath(line_path) if glowIndex > 0: for index in range(3): painter.setPen(self._pen_clear) painter.drawPath(line_path) pen = self._glowRed[glowIndex][index] pen.setCapStyle(qc.Qt.RoundCap) painter.setPen(pen) painter.drawPath(line_path)
def _draw_over_grid(self,painter): # painter.setRenderHint(QPainter.Antialiasing, False) line_color = QColor(60, 20, 200, 255) flat_structure = QColor(20,20,255,128) line_color = flat_structure w = min(self.height(), self.width()) / 20 m = self.margin / 2 x0 = m x1 = m + w x15 = m + 9*w x2 = self.width() - m - w x3 = self.width() - m y0 = m y1 = m + w y15 = m + 5*w y2 = self.height() - m - w y3 = self.height() - m # ---------------------------------------------------------------------- d = w / 4 p = [ (x0,y15+d), (x0,y1), (x1,y0), (x15+2*d,y0), # / (x15+d,y0+d), # ____/ (x1,y0+d), # / (x0+d,y1), # | (x0+d,y15), # | (x0,y15+d) # _| ] qp = QPainterPath() qp.moveTo( p[0][0], p[0][1],) for i in range(1,len(p)): qp.lineTo( p[i][0], p[i][1],) qp.closeSubpath() painter.fillPath(qp,QBrush(QColor(20,20,255,128))) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(line_color) # alpha=255=fully opaque pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp) # --------------------------------------------------------- qp = QPainterPath() p = [ (x0,y1), (x1,y0), (x2,y0), (x3,y1), (x3,y2), (x2,y3), (x1,y3), (x0,y2), (x0,y1)] qp.moveTo( p[0][0], p[0][1],) for i in range(1,len(p)): qp.lineTo( p[i][0], p[i][1],) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(QColor(0, 0, 80, 196)) # alpha=255=fully opaque pen.setWidth(5) painter.setPen(pen) painter.drawPath(qp) pen = QPen() pen.setCapStyle(Qt.RoundCap) pen.setColor(line_color) # alpha=255=fully opaque pen.setWidth(1) painter.setPen(pen) painter.drawPath(qp)
class Square_button_blue(qg.QPushButton): penTick = QPen(QColor(33, 213, 231), 2, qc.Qt.SolidLine) penborder = QPen(QColor(9, 10, 12), 3, qc.Qt.SolidLine) _glowPens = {} for index in range(1, 11): _glowPens[index] = [ QPen(QColor(33, 213, 231, 5 * index), 2, qc.Qt.SolidLine), QPen(QColor(33, 213, 231, 10 * index), 2.5, qc.Qt.SolidLine), QPen(QColor(33, 213, 231, 15 * index), 3, qc.Qt.SolidLine), QPen(QColor(33, 213, 231, 25.5 * index), 6, qc.Qt.SolidLine) ] _pen_text = QPen(QColor(125, 200, 100), 1, qc.Qt.SolidLine) _pen_textHover = QPen(QColor(150, 225, 125), 1, qc.Qt.SolidLine) _pen_Ticktext = QPen(QColor(125, 200, 100), 2, qc.Qt.SolidLine) _pen_TickHover = QPen(QColor(255, 0, 0), 2, qc.Qt.SolidLine) _pen_TickPressed = QPen(QColor(1, 1, 1), 3, qc.Qt.SolidLine) _pen_Shadow = QPen(QColor(9, 10, 12), 2, qc.Qt.SolidLine) _pen_border = QPen(QColor(9, 10, 12), 2, qc.Qt.SolidLine) _pen_clear = QPen(QColor(0, 0, 0, 0), 1, qc.Qt.SolidLine) _penText_disable = QPen(QColor(102, 107, 110), 1, qc.Qt.SolidLine) _penShadow_disable = QPen(QColor(0, 0, 0), 1, qc.Qt.SolidLine) _brushClear = QBrush(QColor(0, 0, 0, 0)) _brushBorder = QBrush(QColor(9, 10, 12)) _gradient = {NORMAL: {}, DOWN: {}, DISABLE: {}} inner_gradient = QLinearGradient(0, 3, 0, 24) inner_gradient.setColorAt(0, QColor(53, 57, 60)) inner_gradient.setColorAt(1, QColor(33, 34, 36)) _gradient[NORMAL][INNER] = QBrush(inner_gradient) outer_gradient = QLinearGradient(0, 2, 0, 25) outer_gradient.setColorAt(0, QColor(69, 73, 76)) outer_gradient.setColorAt(1, QColor(17, 18, 20)) _gradient[NORMAL][OUTER] = QBrush(outer_gradient) inner_gradientDown = QLinearGradient(0, 3, 0, 24) inner_gradientDown.setColorAt(0, QColor(20, 21, 23)) inner_gradientDown.setColorAt(1, QColor(48, 49, 51)) _gradient[DOWN][INNER] = QBrush(inner_gradientDown) outer_gradientDown = QLinearGradient(0, 2, 0, 25) outer_gradientDown.setColorAt(0, QColor(20, 21, 23)) outer_gradientDown.setColorAt(1, QColor(32, 33, 35)) _gradient[DOWN][OUTER] = QBrush(outer_gradientDown) inner_gradientDisable = QLinearGradient(0, 3, 0, 24) inner_gradientDisable.setColorAt(0, QColor(33, 37, 39)) inner_gradientDisable.setColorAt(1, QColor(13, 14, 16)) _gradient[DISABLE][INNER] = QBrush(inner_gradientDisable) outer_gradientDisable = QLinearGradient(0, 2, 0, 25) outer_gradientDisable.setColorAt(0, QColor(49, 53, 56)) outer_gradientDisable.setColorAt(1, QColor(9, 10, 12)) _gradient[DISABLE][OUTER] = QBrush(outer_gradientDisable) _size = [35, 35] def __init__(self, parent=None, *args, **kwargs): super(Square_button_blue, self).__init__(parent, *args, **kwargs) font = qg.QFont() font.setPointSize(12) font.setFamily('Calibri') font.setLetterSpacing(QFont.AbsoluteSpacing, float(1)) self.setFont(font) self.hover = False self._glow_index = 0 self._anim_timer = qc.QTimer() self._anim_timer.timeout.connect(self._animateGlow) self.setFixedSize(self._size[0], self._size[1]) self.fontMetrics = qg.QFontMetrics(font) self.radius = 5 self.setMouseTracking(True) self.setCursor(qg.QCursor(qc.Qt.PointingHandCursor)) self.parent = parent def paintEvent(self, event): painter = qg.QPainter(self) option = qg.QStyleOption() option.initFrom(self) x = option.rect.x() y = option.rect.y() height = option.rect.height() - 1 width = option.rect.width() - 1 painter.setRenderHint(qg.QPainter.Antialiasing) radius = 10 offSet = 0 gradient = self._gradient[NORMAL] glowIndex = self._glow_index glowPen = self._glowPens if self.isDown(): gradient = self._gradient[DOWN] offSet = 1 painter.setBrush(self._brushBorder) painter.setPen(self._pen_border) painter.drawRoundedRect(qc.QRect(x + 1, y + 1, width - 1, height - 1), radius, radius) painter.setPen(self._pen_clear) painter.setBrush(gradient[OUTER]) painter.drawRoundedRect(qc.QRect(x + 2, y + 2, width - 3, height - 3), radius, radius) painter.setBrush(gradient[INNER]) painter.drawRoundedRect(qc.QRect(x + 3, y + 3, width - 4, height - 4), radius - 1, radius - 1) painter.setBrush(self._brushClear) line_path = qg.QPainterPath() #------------------- IK- full ----------# # offset num_x = 5.5 num_y = 2.5 ####################################### # F line_path.moveTo(2 + num_x, 9 + num_y) line_path.lineTo(2 + num_x, 21 + num_y) line_path.moveTo(3 + num_x, 9 + num_y) line_path.lineTo(10 + num_x, 9 + num_y) line_path.moveTo(3 + num_x, 15 + num_y) line_path.lineTo(8 + num_x, 15 + num_y) ######################################### # K num_x = 7 line_path.moveTo(12 + num_x, 9 + num_y) line_path.lineTo(12 + num_x, 21 + num_y) line_path.moveTo(15 + num_x, 15 + num_y) line_path.lineTo(20 + num_x, 10 + num_y) line_path.moveTo(15 + num_x, 15 + num_y) line_path.lineTo(20 + num_x, 21 + num_y) self.penTick.setCapStyle(qc.Qt.RoundCap) if self.isEnabled(): painter.setPen(self.penborder) painter.drawPath(line_path) painter.setPen(self.penTick) painter.drawPath(line_path) if glowIndex > 0: for index in range(3): painter.setPen(self._pen_clear) painter.drawPath(line_path) pen = self._glowPens[glowIndex][index] pen.setCapStyle(qc.Qt.RoundCap) painter.setPen(pen) painter.drawPath(line_path) ################################################################# def _animateGlow(self): if self.hover: if self._glow_index >= 10: self._glow_index = 10 while self._glow_index > 8: self._glow_index -= 0.25 #print self._glow_index if self._glow_index == 8: self._anim_timer.stop() else: self._glow_index += 1 else: if self._glow_index <= 0: self._glow_index = 0 self._anim_timer.stop() else: self._glow_index -= 1 utils.executeDeferred(self.update) #-----------------------------------------------------------------------------------------------# def enterEvent(self, event): if not self.isEnabled(): return self.hover = True self.startAnim() try: main_par = self.parent.parent() getattr(main_par, 'header_label').setText(self.objectName()) except: pass def leaveEvent(self, event): if not self.isEnabled(): return self.hover = False self.startAnim() try: main_par = self.parent.parent() getattr(main_par, 'header_label').setText('') except: pass def startAnim(self): if self._anim_timer.isActive(): return self._anim_timer.start(20)
def _create_pens(self): self.axis_text_pen = QPen() self.axis_text_pen.setCapStyle(Qt.RoundCap) self.axis_text_pen.setColor(QColor(200, 200, 200)) # alpha=255=fully opaque self.axis_text_pen.setWidth(1)
class Round_big_button_hole_red(Square_button_blue): penTick = QPen(QColor(200, 20, 20), 100, qc.Qt.SolidLine) penborder = QPen(QColor(9, 10, 12), 105, qc.Qt.SolidLine) penInner = QPen(QColor(9, 10, 12), 86, qc.Qt.SolidLine) penclear = QPen(QColor(0, 0, 0), 90, qc.Qt.SolidLine) _glowRed = {} pixMap = qg.QPixmap(CIRCULO) for index in range(1, 11): _glowRed[index] = [ QPen(QColor(255, 20, 20, 2 * index), 92, qc.Qt.SolidLine), QPen(QColor(255, 20, 20, 5 * index), 93, qc.Qt.SolidLine), QPen(QColor(255, 20, 20, 10 * index), 100, qc.Qt.SolidLine), QPen(QColor(255, 20, 20, 15 * index), 110, qc.Qt.SolidLine) ] _size = [122, 122] def __inin__(self, *args, **kwargs): super(Round_big_button_hole_red, self).__init__(self, *args, **kwargs) self.setFixedSize(self._size[0], self._size[1]) def paintEvent(self, event): painter = qg.QPainter(self) option = qg.QStyleOption() option.initFrom(self) x = option.rect.x() y = option.rect.y() height = option.rect.height() - 1 width = option.rect.width() - 1 center = option.rect.center() point = qc.QPointF(center.x() + 1.0, center.y() + 1.5) painter.setRenderHint(qg.QPainter.Antialiasing) radius = self.radius offSet = 0 gradient = self._gradient[NORMAL] glowIndex = self._glow_index glowPen = self._glowPens if self.isDown(): gradient = self._gradient[DOWN] offSet = 1 painter.setPen(self._pen_border) painter.drawEllipse(x + 1, y + 1, width - 1, height - 1) painter.setPen(self._pen_clear) painter.setBrush(gradient[OUTER]) painter.drawEllipse(x + 2, y + 2, width - 3, height - 2) painter.setBrush(gradient[INNER]) painter.drawEllipse(x + 3, y + 3, width - 5, height - 4) painter.setBrush(self._brushClear) ################################################## self.penborder.setCapStyle(qc.Qt.RoundCap) self._pen_Ticktext.setCapStyle(qc.Qt.RoundCap) self._pen_TickPressed.setCapStyle(qc.Qt.RoundCap) self._pen_TickHover.setCapStyle(qc.Qt.RoundCap) self.penInner.setCapStyle(qc.Qt.RoundCap) self.penclear.setCapStyle(qc.Qt.RoundCap) painter.setPen(self.penborder) painter.drawPoint(point) painter.setPen(self._pen_Ticktext) painter.drawPoint(point) self.penTick.setCapStyle(qc.Qt.RoundCap) painter.setPen(self.penborder) painter.drawPoint(point) painter.setPen(self.penTick) painter.drawPoint(point) painter.setPen(self.penInner) painter.drawPoint(point) image = qg.QImage(CIRCULO) image.convertToFormat(qg.QImage.Format_ARGB32) image.invertPixels(qg.QImage.InvertRgba) mask = qg.QPixmap.fromImage(image.createAlphaMask(qc.Qt.AutoColor)) scaled = mask.scaled(width + 1, height + 1, qc.Qt.KeepAspectRatio, qc.Qt.SmoothTransformation) self.setMask(scaled) if glowIndex > 0: for index in range(3): painter.setPen(self._pen_clear) painter.drawPoint(point) pen = self._glowRed[glowIndex][index] pen.setCapStyle(qc.Qt.RoundCap) painter.setPen(pen) painter.drawPoint(point)
def addLine(self, x1, y1, x2, y2, pen=QPen(), brush=QBrush()): line = QLineF(x1, self.ysize - y1, x2, self.ysize - y2) return super().addLine(line, pen=pen, brush=brush)
class CustomSlider(qg.QSlider): _pen_dark = qg.QPen(qg.QColor(0, 1, 3), 1, qc.Qt.SolidLine) _pen_bright = qg.QPen(qg.QColor(25, 26, 29), 1.5, qc.Qt.SolidLine) _gradient_inner = qg.QLinearGradient(0, 9, 0, 15) _gradient_inner.setColorAt(0, qg.QColor(69, 73, 66)) _gradient_inner.setColorAt(1, qg.QColor(17, 18, 20)) _gradient_outer = qg.QLinearGradient(0, 9, 0, 15) _gradient_outer.setColorAt(0, qg.QColor(53, 57, 60)) _gradient_outer.setColorAt(1, qg.QColor(33, 34, 36)) _glowBrushes = {} for index in range(1, 11): _glowBrushes[index] = [ QBrush(QColor(0, 255, 0, 1 * index)), QBrush(QColor(0, 255, 0, 3 * index)), QBrush(QColor(0, 255, 0, 15 * index)), QBrush(QColor(0, 255, 0, 25.5 * index)), QBrush(QColor(125, 200, 100, 15 * index)) ] _pen_Shadow = QPen(QColor(9, 10, 12), 1, qc.Qt.SolidLine) _pen_clear = QPen(QColor(0, 0, 0, 0), 1, qc.Qt.SolidLine) _brushClear = QBrush(QColor(0, 0, 0, 0)) _brushBorder = QBrush(QColor(9, 10, 12)) def __init__(self, *args, **kwargs): qg.QSlider.__init__(self, *args, **kwargs) self.setOrientation(qc.Qt.Horizontal) self.setFixedHeight(22) self.setMinimumWidth(50) self.hover = False self._glow_index = 0 self._anim_timer = qc.QTimer() self._anim_timer.timeout.connect(self._animateGlow) self._track = False self._tracking_points = {} self._anim_followTimer = qc.QTimer() self._glow_index2 = 0 self._anim_followTimer.timeout.connect(self._animateGlow2) self._anim_followTimer.timeout.connect(self._removeTrackingPoints) self.valueChanged.connect(self._trackChanges) def setRange(self, *args, **kwargs): qg.QSlider.setRange(self, *args, **kwargs) self._updateTracking() def setMinimum(self, *args, **kwargs): qg.QSlider.setMinimum(self, *args, **kwargs) self._updateTracking() def setMaximum(self, *args, **kwargs): qg.QSlider.setMaximum(self, *args, **kwargs) self._updateTracking() def _updateTracking(self): self._tracking_points = [0 ] * (abs(self.maximum() - self.minimum()) + 1) def setValue(self, *args, **kwargs): qg.QSlider.setValue(self, *args, **kwargs) for index in range(len(self._tracking_points)): self._tracking_points[index] = 0 #-----------------------------------------------------------------------------------------------# def mouseMoveEvent(self, event): qg.QSlider.mouseMoveEvent(self, event) if self._anim_followTimer.isActive(): return self._anim_followTimer.start(20) #-----------------------------------------------------------------------------------------------# def _trackChanges(self, value): value = value - self.minimum() self._tracking_points[value] = 10 #-----------------------------------------------------------------------------------------------# def _removeTrackingPoints(self): self._track = False for index, value in enumerate(self._tracking_points): if value > 0: self._tracking_points[index] -= 1 if value == 0: self._anim_followTimer.stop() self._track = True if self._track is False: self._anim_followTimer.stop() #-----------------------------------------------------------------------------------------------# def _animateGlow2(self): if self._glow_index2 >= 10: self._glow_index2 = 10 while self._glow_index2 > 0: self._glow_index2 -= 1 if self._glow_index2 == 0: self._anim_followTimer.stop() self.update() #-----------------------------------------------------------------------------------------------# def _animateGlow(self): if self.hover: if self._glow_index >= 10: self._glow_index = 10 while self._glow_index > 8: self._glow_index -= 0.25 if self._glow_index == 8: self._anim_timer.stop() else: self._glow_index += 1 else: if self._glow_index <= 0: self._glow_index = 0 self._anim_timer.stop() else: self._glow_index -= 1 #print self._glow_index utils.executeDeferred(self.update) #-----------------------------------------------------------------------------------------------# def enterEvent(self, event): if not self.isEnabled(): return self.hover = True self._startAnim() def leaveEvent(self, event): if not self.isEnabled(): return self.hover = False self._startAnim() def _startAnim(self): if self._anim_timer.isActive(): return self._anim_timer.start(20) #-----------------------------------------------------------------------------------------------------# def paintEvent(self, event): painter = qg.QPainter(self) option = qg.QStyleOption() option.initFrom(self) x = option.rect.x() y = option.rect.y() height = option.rect.height() - 1 width = option.rect.width() - 1 painter.setRenderHint(qg.QPainter.Antialiasing) painter.setRenderHint(qg.QPainter.TextAntialiasing) painter.setPen(self._pen_Shadow) painter.setBrush(self._brushBorder) painter.drawRoundedRect(qc.QRect(x + 1, y + 1, width - 1, height - 1), 10, 10) mid_height = (height / 2) + 1 painter.setPen(self._pen_dark) painter.drawLine(10, mid_height, width - 8, mid_height) painter.setRenderHint(qg.QPainter.Antialiasing, False) painter.setPen(self._pen_bright) painter.drawLine(10, mid_height, width - 8, mid_height) painter.setRenderHint(qg.QPainter.Antialiasing, True) minimum = self.minimum() maximum = self.maximum() value_range = maximum - minimum value = self.value() - minimum increment = ((width - 20) / float(value_range)) center = 10 + (increment * value) center_point = qc.QPoint(x + center, y + mid_height) painter.setPen(self._pen_clear) glowIndex = self._glow_index glowBrushes = self._glowBrushes if self._track is True: for index, track_value in enumerate(self._tracking_points): if track_value == 0: continue track_center = 10 + (increment * index) painter.setBrush(glowBrushes[track_value][4]) painter.drawEllipse(qc.QPoint(track_center, mid_height), 7, 7) if glowIndex > 0: for index, size in zip(range(4), range(13, 8, -1)): painter.setBrush(glowBrushes[glowIndex][index]) painter.drawEllipse(center_point, size, size) painter.setBrush(qg.QBrush(self._gradient_outer)) painter.drawEllipse(center_point, 8, 8) painter.setBrush(qg.QBrush(self._gradient_inner)) painter.drawEllipse(center_point, 7, 7)
def __init__(self, parent, xvals, G, ylim=(0, 1), grid=True, xlabel=None, ylabel=None, title=None, colors=DEFAULT_COLORS, size=(1200, 600), legend=None, legendpos=None): """ Initialize a bar scene Args: xvals: labels and x positions of the bars G: Number of bars per x value ylim: y limits of the figure xlabel: label below x-axis ylabel: label on left side of the y-axis title: figure title colors: color cycler size: size of the plot in pixels legend: list of legend strings to show. legendpos: position of legend w.r.t. default position, in pixels """ super().__init__(parent=parent) self.setSceneRect(QRect(0, 0, *size)) # self.setBackgroundBrush(ASCEEColors.bgBrush(0, size[0])) self.ylim = ylim N = len(xvals) self.N = N self.G = G self.bgs = [] self.size = size xsize, ysize = size self.xsize = xsize self.ysize = ysize self.colors = colors # Size of the frame Lx = xsize - rightoffset - leftoffset Ly = ysize - topoffset - bottomoffset # The main frame where the bars are in. mainframe = self.createRect(leftoffset, bottomoffset, Lx, Ly) # Set the y ticks and ticklabels self.yticks = [] txtmaxwidth = 0 for i in range(nyticks): y = bottomoffset+Ly*i/(nyticks-1) ytick = self.addLine(leftoffset, y, leftoffset-ticklength, y) if grid: ygrid = self.addLine(leftoffset, y, xsize-rightoffset, y, pen=QPen(Qt.gray)) range_ = ylim[1]-ylim[0] ytickval = i/(nyticks-1)*range_ + ylim[0] yticklabel = f'{ytickval:.0f}' txt = graphicsTextItem(yticklabel) txtwidth = txt.boundingRect().width() txtmaxwidth = max(txtmaxwidth, txtwidth) txt.setPos(leftoffset-10-txtwidth, ysize - y-.022*self.ysize) self.addItem(txt) self.yticks.append(ytick) # Main frame added after grid lines, to get the color right self.addItem(mainframe) # Create the bars for g in range(G): bg = [] for n in range(N): barrect = self.getBarRect(n, g, 0) baritem = QGraphicsRectItem(barrect, brush=QBrush(Qt.blue)) self.addItem(baritem) bg.append(baritem) self.bgs.append(bg) # Add x ticks and ticklabels xticklabels = [] for n in range(N): xticklabel = f'{xvals[n]}' txt = graphicsTextItem(xticklabel) txtxpos = self.getBarGroupMidPos(n)-12 txt.setPos(txtxpos, self.ysize-bottomoffset+xticklabeloffset) txt.rotate(-90) self.addItem(txt) xticklabels.append(txt) # Set xlabel if xlabel is not None: xlabel = graphicsTextItem(xlabel) width = xlabel.boundingRect().width() txtxpos = xsize/2-width/2 txtypos = ysize - xlabelbottomoffset xlabel.setPos(txtxpos, txtypos) self.addItem(xlabel) # # Set ylabel if ylabel is not None: ylabel = graphicsTextItem(ylabel) ylabel.setPos(ylabelleftoffset, (ysize-topoffset-bottomoffset)/2+topoffset) ylabel.rotate(-90) self.addItem(ylabel) # Set title if title is not None: title = graphicsTextItem(title) width = xlabel.boundingRect().width() txtxpos = self.xsize/2-width/2 txtypos = (1-.998)*self.ysize title.setPos(txtxpos, txtypos) self.addItem(title) if legend is not None: maxlegtxtwidth = 0 legposx, legposy = (0, 0) if legendpos is None else legendpos legpos = (xsize-rightoffset-300+legposx, ysize-topoffset-30+legposy) dyleg = 15 dylegtxt = dyleg Lylegrect = 10 Lxlegrect = 20 legrectmargin = 5 boxtopleft = QPointF(legpos[0]-legrectmargin, ysize-legpos[1]-Lylegrect-legrectmargin) legbox = self.addRect(QRectF(0, 0, 0, 0), pen=QPen(), brush=QBrush(Qt.white)) for i, leg in enumerate(legend): leglabel = legend[i] # The position of the legend, in screen coordinates pos = (legpos[0], legpos[1] - i*dyleg) color = self.colors[i % len(self.colors)] legrect = self.createRect(*pos, Lxlegrect, Lylegrect) legrect.setBrush(QBrush(color)) legtxt = graphicsTextItem(leglabel) maxlegtxtwidth = max(maxlegtxtwidth, legtxt.boundingRect().width()) self.addItem(legrect) self.addItem(legtxt) legtxt.setPos(legpos[0]+Lxlegrect, ysize-pos[1]-dylegtxt-3) legboxsize = QSize(maxlegtxtwidth+Lxlegrect+2*legrectmargin, (i+1)*dyleg+legrectmargin) legboxrect = QRectF(boxtopleft, legboxsize) legbox.setRect(legboxrect)
def _draw_horizontal_ruler(self, painter, text, y_value, color): y = y_value * self.y_factor pen = QPen() pen.setCapStyle(Qt.SquareCap) pen.setColor(color) qp = QPainterPath() r = QRect(1,1,1000,1000) bb = painter.boundingRect(r,Qt.AlignLeft,text) bb = QRect(self.x_base,self.y_base - y - bb.height(), bb.width() + 2, bb.height()) # print("{} {} {} {}".format(bb.x(),bb.y(),bb.width(),bb.height())) fill_color = QColor(0,0,0) fill_color.setAlpha(128) brush = QBrush(fill_color) painter.fillRect(bb,brush) qp.moveTo(self.x_base,self.y_base - y) qp.lineTo(self.total_width + self.x_base, self.y_base - y) painter.setPen(pen) painter.drawPath(qp) text_pen = QPen() text_pen.setCapStyle(Qt.RoundCap) text_pen.setColor(color) # alpha=255=fully opaque text_pen.setWidth(1) painter.setPen(text_pen) painter.drawText(self.x_base,self.y_base - y - 5,text)