def drawForeground(self, painter, rect): """ Draws the foreground for this scene. :param painter | <QPainter> rect | <QRect> """ gantt = self.ganttWidget() header = gantt.treeWidget().header() width = self.sceneRect().width() height = header.height() # create the main color palette = gantt.palette() color = palette.color(palette.Button) textColor = palette.color(palette.ButtonText) borderColor = color.darker(140) text_align = Qt.AlignBottom | Qt.AlignHCenter y = rect.top() # create the gradient gradient = QLinearGradient() gradient.setStart(0, y) gradient.setFinalStop(0, y + height) gradient.setColorAt(0, color) gradient.setColorAt(1, color.darker(120)) painter.setBrush(QBrush(gradient)) painter.drawRect(0, y, width, height) # add top labels for rect, label in self._topLabels: rx = rect.x() ry = rect.y() + y rw = rect.width() rh = rect.height() painter.setPen(borderColor) painter.drawRect(rx, ry, rw, rh) painter.setPen(textColor) painter.drawText(rx, ry, rw, rh - 2, text_align, label) # add bottom labels for rect, label in self._labels: rx = rect.x() ry = rect.y() + y rw = rect.width() rh = rect.height() painter.setPen(borderColor) painter.drawRect(rx, ry, rw, rh) painter.setPen(textColor) painter.drawText(rx, ry, rw, rh - 2, text_align, label)
def drawForeground( self, painter, rect ): """ Draws the foreground for this scene. :param painter | <QPainter> rect | <QRect> """ gantt = self.ganttWidget() header = gantt.treeWidget().header() width = self.sceneRect().width() height = header.height() # create the main color palette = gantt.palette() color = palette.color(palette.Button) textColor = palette.color(palette.ButtonText) borderColor = color.darker(140) text_align = Qt.AlignBottom | Qt.AlignHCenter y = rect.top() # create the gradient gradient = QLinearGradient() gradient.setStart(0, y) gradient.setFinalStop(0, y + height) gradient.setColorAt(0, color) gradient.setColorAt(1, color.darker(120)) painter.setBrush(QBrush(gradient)) painter.drawRect(0, y, width, height) # add top labels for rect, label in self._topLabels: rx = rect.x() ry = rect.y() + y rw = rect.width() rh = rect.height() painter.setPen(borderColor) painter.drawRect(rx, ry, rw, rh) painter.setPen(textColor) painter.drawText(rx, ry, rw, rh - 2, text_align, label) # add bottom labels for rect, label in self._labels: rx = rect.x() ry = rect.y() + y rw = rect.width() rh = rect.height() painter.setPen(borderColor) painter.drawRect(rx, ry, rw, rh) painter.setPen(textColor) painter.drawText(rx, ry, rw, rh - 2, text_align, label)
def _gen_striped_gradient(basecolor): """Just generate a standard gradient, for use as a background""" g = QLinearGradient() g.setSpread(g.ReflectSpread) g.setStart(0,0) g.setFinalStop(2, 2) g.setColorAt(0.0, QColor(basecolor)) g.setColorAt(0.35, QColor(0,0,0,0)) g.setColorAt(0.75, QColor(0,0,0,0)) g.setColorAt(1.0, QColor(basecolor)) return g
def paintMilestone(self, painter): """ Paints this item as the milestone look. :param painter | <QPainter> """ # generate the rect rect = self.rect() padding = self.padding() gantt = self.scene().ganttWidget() cell_w = gantt.cellWidth() cell_h = gantt.cellHeight() x = rect.width() - cell_w y = self.padding() w = cell_w h = rect.height() - padding - 2 # grab the color options color = self.color() alt_color = self.alternateColor() if (self.isSelected()): color = self.highlightColor() alt_color = self.alternateHighlightColor() # create the background brush gradient = QLinearGradient() gradient.setStart(0, 0) gradient.setFinalStop(0, h) gradient.setColorAt(0, color) gradient.setColorAt(0.8, alt_color) gradient.setColorAt(1, color) painter.setPen(self.borderColor()) painter.setBrush(QBrush(gradient)) pen = painter.pen() pen.setWidthF(0.5) painter.setPen(pen) painter.setRenderHint(painter.Antialiasing) path = QPainterPath() path.moveTo(x - cell_w / 3.0, y + h / 2.0) path.lineTo(x, y) path.lineTo(x + cell_w / 3.0, y + h / 2.0) path.lineTo(x, y + h) path.lineTo(x - cell_w / 3.0, y + h / 2.0) painter.drawPath(path)
def paint(self, painter, option, widget): widget = self.scene()._slider pixmap = self.pixmap() palette = widget.palette() base = palette.color(palette.Base) # draw the reflection painter.save() painter.setPen(Qt.NoPen) transform = painter.transform() transform.translate(pixmap.width() / 2.0, 0) transform.rotate(self.angle(), Qt.YAxis) transform.translate(-pixmap.width() / 2.0, 0) painter.setTransform(transform) self.graphicsEffect().setEnabled(self.isSelected()) painter.drawPixmap(0, 0, pixmap) painter.setBrush(Qt.NoBrush) painter.setOpacity(0.2) painter.scale(1, -1) painter.translate(0, -(pixmap.height()) * 2) painter.drawPixmap(0, 0, pixmap) painter.setOpacity(1) grad = QLinearGradient() grad.setStart(0, 0) grad.setFinalStop(0, pixmap.height()) grad.setColorAt(1.0, QColor(0, 0, 0, 0)) grad.setColorAt(0.2, base) grad.setColorAt(0.0, base) painter.setBrush(grad) painter.drawRect(0, 0, pixmap.width(), pixmap.height()) painter.restore()
def drawItem(self, item, painter, option): """ Draws the inputed item as a bar graph. :param item | <XChartDatasetItem> painter | <QPainter> option | <QStyleOptionGraphicsItem> """ dataset = item.dataset() painter.save() painter.setRenderHint(painter.Antialiasing) pen = QPen(dataset.color()) pen.setWidth(0.75) painter.setPen(pen) for path in item.buildData('subpaths', []): gradient = QLinearGradient() clr = QColor(dataset.color()) clr.setAlpha(220) gradient.setColorAt(0.0, clr.lighter(180)) gradient.setColorAt(0.1, clr.lighter(160)) gradient.setColorAt(0.25, clr.lighter(140)) gradient.setColorAt(1.0, clr.lighter(125)) if self.orientation() == Qt.Vertical: gradient.setStart(0, path.boundingRect().bottom()) gradient.setFinalStop(0, path.boundingRect().top()) else: gradient.setStart(path.boundingRect().left(), 0) gradient.setFinalStop(path.boundingRect().right(), 0) painter.setBrush(gradient) painter.drawPath(path) painter.restore()
def drawForeground(self, painter, rect): palette = self._slider.palette() color = palette.color(palette.Base) trans = self._slider.viewportTransform() rect = trans.mapRect(self._slider.rect()) width = rect.width() rect.setX(abs(rect.x())) rect.setWidth(width) clear = QColor(0, 0, 0, 0) grad = QLinearGradient() grad.setStart(rect.left(), 0) grad.setFinalStop(rect.right(), 0) grad.setColorAt(0.0, color) grad.setColorAt(0.3, clear) grad.setColorAt(0.7, clear) grad.setColorAt(1.0, color) painter.setBrush(grad) painter.setPen(Qt.NoPen) painter.drawRect(rect)
class PixmapDial(QDial): # enum CustomPaint CUSTOM_PAINT_NULL = 0 CUSTOM_PAINT_CARLA_WET = 1 CUSTOM_PAINT_CARLA_VOL = 2 CUSTOM_PAINT_CARLA_L = 3 CUSTOM_PAINT_CARLA_R = 4 # enum Orientation HORIZONTAL = 0 VERTICAL = 1 HOVER_MIN = 0 HOVER_MAX = 9 def __init__(self, parent): QDial.__init__(self, parent) self.fPixmap = QPixmap("./bitmaps/dial_01d.png") self.fPixmapNum = "01" self.fCustomPaint = self.CUSTOM_PAINT_NULL self.fHovered = False self.fHoverStep = self.HOVER_MIN if self.fPixmap.width() > self.fPixmap.height(): self.fOrientation = self.HORIZONTAL else: self.fOrientation = self.VERTICAL self.fLabel = "" self.fLabelPos = QPointF(0.0, 0.0) self.fLabelFont = QFont() self.fLabelFont.setPointSize(6) self.fLabelWidth = 0 self.fLabelHeight = 0 self.fLabelGradient = QLinearGradient(0, 0, 0, 1) if self.palette().window().color().lightness() > 100: # Light background c = self.palette().dark().color() self.fColor1 = c self.fColor2 = QColor(c.red(), c.green(), c.blue(), 0) self.fColorT = [self.palette().buttonText().color(), self.palette().mid().color()] else: # Dark background self.fColor1 = QColor(0, 0, 0, 255) self.fColor2 = QColor(0, 0, 0, 0) self.fColorT = [Qt.white, Qt.darkGray] self.updateSizes() def getSize(self): return self.fSize def setCustomPaint(self, paint): self.fCustomPaint = paint self.fLabelPos.setY(self.fSize + self.fLabelHeight/2) self.update() def setEnabled(self, enabled): if self.isEnabled() != enabled: self.fPixmap.load("./bitmaps/dial_%s%s.png" % (self.fPixmapNum, "" if enabled else "d")) self.updateSizes() self.update() QDial.setEnabled(self, enabled) def setLabel(self, label): self.fLabel = label self.fLabelWidth = QFontMetrics(self.fLabelFont).width(label) self.fLabelHeight = QFontMetrics(self.fLabelFont).height() self.fLabelPos.setX(float(self.fSize)/2.0 - float(self.fLabelWidth)/2.0) self.fLabelPos.setY(self.fSize + self.fLabelHeight) self.fLabelGradient.setColorAt(0.0, self.fColor1) self.fLabelGradient.setColorAt(0.6, self.fColor1) self.fLabelGradient.setColorAt(1.0, self.fColor2) self.fLabelGradient.setStart(0, float(self.fSize)/2.0) self.fLabelGradient.setFinalStop(0, self.fSize + self.fLabelHeight + 5) self.fLabelGradientRect = QRectF(float(self.fSize)/8.0, float(self.fSize)/2.0, float(self.fSize*6)/8.0, self.fSize+self.fLabelHeight+5) self.update() def setPixmap(self, pixmapId): self.fPixmapNum = "%02i" % pixmapId self.fPixmap.load("./bitmaps/dial_%s%s.png" % (self.fPixmapNum, "" if self.isEnabled() else "d")) if self.fPixmap.width() > self.fPixmap.height(): self.fOrientation = self.HORIZONTAL else: self.fOrientation = self.VERTICAL self.updateSizes() self.update() def minimumSizeHint(self): return QSize(self.fSize, self.fSize) def sizeHint(self): return QSize(self.fSize, self.fSize) def updateSizes(self): self.fWidth = self.fPixmap.width() self.fHeight = self.fPixmap.height() if self.fWidth < 1: self.fWidth = 1 if self.fHeight < 1: self.fHeight = 1 if self.fOrientation == self.HORIZONTAL: self.fSize = self.fHeight self.fCount = self.fWidth / self.fHeight else: self.fSize = self.fWidth self.fCount = self.fHeight / self.fWidth self.setMinimumSize(self.fSize, self.fSize + self.fLabelHeight + 5) self.setMaximumSize(self.fSize, self.fSize + self.fLabelHeight + 5) def enterEvent(self, event): self.fHovered = True if self.fHoverStep == self.HOVER_MIN: self.fHoverStep = self.HOVER_MIN + 1 QDial.enterEvent(self, event) def leaveEvent(self, event): self.fHovered = False if self.fHoverStep == self.HOVER_MAX: self.fHoverStep = self.HOVER_MAX - 1 QDial.leaveEvent(self, event) def paintEvent(self, event): event.accept() painter = QPainter(self) painter.save() painter.setRenderHint(QPainter.Antialiasing, True) if self.fLabel: if self.fCustomPaint == self.CUSTOM_PAINT_NULL: painter.setPen(self.fColor2) painter.setBrush(self.fLabelGradient) painter.drawRect(self.fLabelGradientRect) painter.setFont(self.fLabelFont) painter.setPen(self.fColorT[0 if self.isEnabled() else 1]) painter.drawText(self.fLabelPos, self.fLabel) if self.isEnabled(): current = float(self.value() - self.minimum()) divider = float(self.maximum() - self.minimum()) if divider == 0.0: return value = current / divider target = QRectF(0.0, 0.0, self.fSize, self.fSize) per = int((self.fCount - 1) * value) if self.fOrientation == self.HORIZONTAL: xpos = self.fSize * per ypos = 0.0 else: xpos = 0.0 ypos = self.fSize * per source = QRectF(xpos, ypos, self.fSize, self.fSize) painter.drawPixmap(target, self.fPixmap, source) # Custom knobs (Dry/Wet and Volume) if self.fCustomPaint in (self.CUSTOM_PAINT_CARLA_WET, self.CUSTOM_PAINT_CARLA_VOL): # knob color colorGreen = QColor(0x5D, 0xE7, 0x3D, 191 + self.fHoverStep*7) colorBlue = QColor(0x3E, 0xB8, 0xBE, 191 + self.fHoverStep*7) # draw small circle ballRect = QRectF(8.0, 8.0, 15.0, 15.0) ballPath = QPainterPath() ballPath.addEllipse(ballRect) #painter.drawRect(ballRect) tmpValue = (0.375 + 0.75*value) ballValue = tmpValue - floor(tmpValue) ballPoint = ballPath.pointAtPercent(ballValue) # draw arc startAngle = 216*16 spanAngle = -252*16*value if self.fCustomPaint == self.CUSTOM_PAINT_CARLA_WET: painter.setBrush(colorBlue) painter.setPen(QPen(colorBlue, 0)) painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.2, 2.2)) gradient = QConicalGradient(15.5, 15.5, -45) gradient.setColorAt(0.0, colorBlue) gradient.setColorAt(0.125, colorBlue) gradient.setColorAt(0.625, colorGreen) gradient.setColorAt(0.75, colorGreen) gradient.setColorAt(0.76, colorGreen) gradient.setColorAt(1.0, colorGreen) painter.setBrush(gradient) painter.setPen(QPen(gradient, 3)) else: painter.setBrush(colorBlue) painter.setPen(QPen(colorBlue, 0)) painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.2, 2.2)) painter.setBrush(colorBlue) painter.setPen(QPen(colorBlue, 3)) painter.drawArc(4.0, 4.0, 26.0, 26.0, startAngle, spanAngle) # Custom knobs (L and R) elif self.fCustomPaint in (self.CUSTOM_PAINT_CARLA_L, self.CUSTOM_PAINT_CARLA_R): # knob color color = QColor(0xAD + self.fHoverStep*5, 0xD5 + self.fHoverStep*4, 0x4B + self.fHoverStep*5) # draw small circle ballRect = QRectF(7.0, 8.0, 11.0, 12.0) ballPath = QPainterPath() ballPath.addEllipse(ballRect) #painter.drawRect(ballRect) tmpValue = (0.375 + 0.75*value) ballValue = tmpValue - floor(tmpValue) ballPoint = ballPath.pointAtPercent(ballValue) painter.setBrush(color) painter.setPen(QPen(color, 0)) painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.0, 2.0)) # draw arc if self.fCustomPaint == self.CUSTOM_PAINT_CARLA_L: startAngle = 216*16 spanAngle = -252.0*16*value elif self.fCustomPaint == self.CUSTOM_PAINT_CARLA_R: startAngle = 324.0*16 spanAngle = 252.0*16*(1.0-value) else: return painter.setPen(QPen(color, 2)) painter.drawArc(3.5, 4.5, 22.0, 22.0, startAngle, spanAngle) if self.HOVER_MIN < self.fHoverStep < self.HOVER_MAX: self.fHoverStep += 1 if self.fHovered else -1 QTimer.singleShot(20, self, SLOT("update()")) else: # isEnabled() target = QRectF(0.0, 0.0, self.fSize, self.fSize) painter.drawPixmap(target, self.fPixmap, target) painter.restore() def resizeEvent(self, event): self.updateSizes() QDial.resizeEvent(self, event)
class OWLegendGradient(QGraphicsObject): gradient_width = 20 def __init__(self, palette, values, parent): QGraphicsObject.__init__(self, parent) self.parent = parent self.palette = palette self.values = values self.legend = parent self.label_items = [QGraphicsTextItem(text, self) for text in values] for i in self.label_items: i.setTextWidth(50) self.rect = QRectF() self.gradient_item = QGraphicsRectItem(self) self.gradient = QLinearGradient() self.gradient.setStops([(v*0.1, self.palette[v*0.1]) for v in range(11) ]) self.orientation = Qt.Horizontal self.set_orientation(Qt.Vertical) def set_orientation(self, orientation): if self.orientation == orientation: return self.orientation = orientation if self.orientation == Qt.Vertical: height = max([item.boundingRect().height() for item in self.label_items]) total_height = height * max(5, len(self.label_items)) interval = (total_height - self.label_items[-1].boundingRect().height()) / (len(self.label_items) -1) self.gradient_item.setRect(10, 0, self.gradient_width, total_height) self.gradient.setStart(10, 0) self.gradient.setFinalStop(10, total_height) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) y = 0 x = 30 for item in self.label_items: move_item_xy(item, x, y, self.parent.graph.animate_plot) y += interval self.rect = QRectF(10, 0, self.gradient_width + max([item.boundingRect().width() for item in self.label_items]), self.label_items[0].boundingRect().height() * max(5, len(self.label_items))) else: width = 50 height = max([item.boundingRect().height() for item in self.label_items]) total_width = width * max(5, len(self.label_items)) interval = (total_width - self.label_items[-1].boundingRect().width()) / (len(self.label_items) -1) self.gradient_item.setRect(0, 0, total_width, self.gradient_width) self.gradient.setStart(0, 0) self.gradient.setFinalStop(total_width, 0) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) x = 0 y = 30 for item in self.label_items: move_item_xy(item, x, y, self.parent.graph.animate_plot) x += interval self.rect = QRectF(0, 0, total_width, self.gradient_width + height) def boundingRect(self): return getattr(self, 'rect', QRectF()) def paint(self, painter, option, widget): pass
def paintGroup(self, painter): """ Paints this item as the group look. :param painter | <QPainter> """ # generate the rect rect = self.rect() padding = self.padding() gantt = self.scene().ganttWidget() cell_w = gantt.cellWidth() cell_h = gantt.cellHeight() x = 0 y = self.padding() w = rect.width() h = rect.height() - (padding + 1) # grab the color options color = self.color() alt_color = self.alternateColor() if (self.isSelected()): color = self.highlightColor() alt_color = self.alternateHighlightColor() # create the background brush gradient = QLinearGradient() gradient.setStart(0, 0) gradient.setFinalStop(0, h) gradient.setColorAt(0, color) gradient.setColorAt(0.8, alt_color) gradient.setColorAt(1, color) painter.setPen(self.borderColor()) painter.setBrush(QBrush(gradient)) pen = painter.pen() pen.setWidthF(0.5) painter.setPen(pen) painter.setRenderHint(painter.Antialiasing) path = QPainterPath() path.moveTo(x - cell_w / 4.0, y) path.lineTo(w + cell_w / 4.0, y) path.lineTo(w + cell_w / 4.0, y + h / 2.0) path.lineTo(w, h) path.lineTo(w - cell_w / 4.0, y + h / 2.0) path.lineTo(x + cell_w / 4.0, y + h / 2.0) path.lineTo(x, h) path.lineTo(x - cell_w / 4.0, y + h / 2.0) path.lineTo(x - cell_w / 4.0, y) painter.drawPath(path) # create the progress brush if (self.showProgress()): gradient = QLinearGradient() gradient.setStart(0, 0) gradient.setFinalStop(0, h) gradient.setColorAt(0, self.progressColor()) gradient.setColorAt(0.8, self.alternateProgressColor()) gradient.setColorAt(1, self.progressColor()) prog_w = (w - 4) * (self._percentComplete / 100.0) painter.setPen(Qt.NoPen) painter.setBrush(QBrush(gradient)) painter.drawRect(x, y, prog_w, y + h / 2.0) # draw the text on this item if (self.text()): painter.setPen(self.textColor()) painter.drawText(x, y, w, h, Qt.AlignTop, self.text())
class GradientLegendItem(QGraphicsObject, GraphicsWidgetAnchor): gradient_width = 20 def __init__(self, title, palette, values, parent): QGraphicsObject.__init__(self, parent) GraphicsWidgetAnchor.__init__(self) self.parent = self.legend = parent self.palette = palette self.values = values self.title = QGraphicsTextItem('%s:' % title, self) f = self.title.font() f.setBold(True) self.title.setFont(f) self.title_item = QGraphicsRectItem(self.title.boundingRect(), self) self.title_item.setPen(QPen(Qt.NoPen)) self.title_item.stackBefore(self.title) self.label_items = [QGraphicsTextItem(text, self) for text in values] for i in self.label_items: i.setTextWidth(50) self.rect = QRectF() self.gradient_item = QGraphicsRectItem(self) self.gradient = QLinearGradient() self.gradient.setStops([(v * 0.1, self.palette[v * 0.1]) for v in range(11)]) self.orientation = Qt.Horizontal self.set_orientation(Qt.Vertical) self.setFlag(QGraphicsItem.ItemIgnoresTransformations, True) self.setFlag(QGraphicsItem.ItemIsMovable, True) def set_orientation(self, orientation): return if self.orientation == orientation: return self.orientation = orientation if self.orientation == Qt.Vertical: height = max(item.boundingRect().height() for item in self.label_items) total_height = height * max(5, len(self.label_items)) interval = (total_height - self.label_items[-1].boundingRect().height() ) / (len(self.label_items) - 1) self.gradient_item.setRect(10, 0, self.gradient_width, total_height) self.gradient.setStart(10, 0) self.gradient.setFinalStop(10, total_height) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) y = -20 # hja, no; dela --> pri boundingRect() zato pristejem +20 x = 0 move_item_xy(self.title, x, y, False) y = 10 x = 30 for item in self.label_items: move_item_xy(item, x, y, False) # self.parent.graph.animate_plot) y += interval self.rect = QRectF(10, 0, self.gradient_width + max(item.boundingRect().width() for item in self.label_items), self.label_items[0].boundingRect().height() * max(5, len(self.label_items))) else: # za horizontalno orientacijo nisem dodajal title-a width = 50 height = max(item.boundingRect().height() for item in self.label_items) total_width = width * max(5, len(self.label_items)) interval = (total_width - self.label_items[-1].boundingRect().width() ) / (len(self.label_items) - 1) self.gradient_item.setRect(0, 0, total_width, self.gradient_width) self.gradient.setStart(0, 0) self.gradient.setFinalStop(total_width, 0) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) x = 0 y = 30 for item in self.label_items: move_item_xy(item, x, y, False) # self.parent.graph.animate_plot) x += interval self.rect = QRectF(0, 0, total_width, self.gradient_width + height) # noinspection PyPep8Naming def boundingRect(self): width = max(self.rect.width(), self.title_item.boundingRect().width()) height = self.rect.height() + self.title_item.boundingRect().height() return QRectF(self.rect.left(), self.rect.top(), width, height) def paint(self, painter, option, widget): pass
def paintEvent(self, event): """ Paints the background for the dock toolbar. :param event | <QPaintEvent> """ x = 1 y = 1 w = self.width() h = self.height() clr_a = QColor(220, 220, 220) clr_b = QColor(190, 190, 190) grad = QLinearGradient() grad.setColorAt(0.0, clr_a) grad.setColorAt(0.6, clr_a) grad.setColorAt(1.0, clr_b) # adjust the coloring for the horizontal toolbar if self.position() & (self.Position.North | self.Position.South): h = self.minimumPixmapSize().height() + 6 if self.position() == self.Position.South: y = self.height() - h grad.setStart(0, y) grad.setFinalStop(0, self.height()) else: grad.setStart(0, 0) grad.setFinalStart(0, h) # adjust the coloring for the vertical toolbar if self.position() & (self.Position.East | self.Position.West): w = self.minimumPixmapSize().width() + 6 if self.position() == self.Position.West: x = self.width() - w grad.setStart(x, 0) grad.setFinalStop(self.width(), 0) else: grad.setStart(0, 0) grad.setFinalStop(w, 0) painter = QPainter(self) painter.fillRect(x, y, w, h, grad) # show the active action action = self.selectedAction() if action is not None and \ not self.currentAction() and \ not self._animating: for lbl in self.actionLabels(): if lbl.action() != action: continue geom = lbl.geometry() size = lbl.pixmapSize() if self.position() == self.Position.North: x = geom.left() y = 0 w = geom.width() h = size.height() + geom.top() + 2 elif self.position() == self.Position.East: x = 0 y = geom.top() w = size.width() + geom.left() + 2 h = geom.height() painter.setPen(QColor(140, 140, 40)) painter.setBrush(QColor(160, 160, 160)) painter.drawRect(x, y, w, h) break
class PixmapDial(QDial): HORIZONTAL = 0 VERTICAL = 1 CUSTOM_PAINT_CARLA_WET = 1 CUSTOM_PAINT_CARLA_VOL = 2 CUSTOM_PAINT_CARLA_L = 3 CUSTOM_PAINT_CARLA_R = 4 HOVER_MIN = 0 HOVER_MAX = 9 def __init__(self, parent): QDial.__init__(self, parent) self.m_pixmap = QPixmap(":/bitmaps/dial_01d.png") self.m_pixmap_n_str = "01" self.m_custom_paint = 0 self.m_hovered = False self.m_hover_step = self.HOVER_MIN if self.m_pixmap.width() > self.m_pixmap.height(): self.m_orientation = self.HORIZONTAL else: self.m_orientation = self.VERTICAL self.m_label = "" self.m_label_pos = QPointF(0.0, 0.0) self.m_label_width = 0 self.m_label_height = 0 self.m_label_gradient = QLinearGradient(0, 0, 0, 1) if self.palette().window().color().lightness() > 100: # Light background self.m_color1 = QColor(100, 100, 100, 255) self.m_color2 = QColor(0, 0, 0, 0) self.m_colorT = [self.palette().text().color(), self.palette().mid().color()] else: # Dark background self.m_color1 = QColor(0, 0, 0, 255) self.m_color2 = QColor(0, 0, 0, 0) self.m_colorT = [Qt.white, Qt.darkGray] self.updateSizes() def getSize(self): return self.p_size def setCustomPaint(self, paint): self.m_custom_paint = paint self.update() def setEnabled(self, enabled): if self.isEnabled() != enabled: self.m_pixmap.load(":/bitmaps/dial_%s%s.png" % (self.m_pixmap_n_str, "" if enabled else "d")) self.updateSizes() self.update() QDial.setEnabled(self, enabled) def setLabel(self, label): self.m_label = label self.m_label_width = QFontMetrics(self.font()).width(label) self.m_label_height = QFontMetrics(self.font()).height() self.m_label_pos.setX((self.p_size / 2) - (self.m_label_width / 2)) self.m_label_pos.setY(self.p_size + self.m_label_height) self.m_label_gradient.setColorAt(0.0, self.m_color1) self.m_label_gradient.setColorAt(0.6, self.m_color1) self.m_label_gradient.setColorAt(1.0, self.m_color2) self.m_label_gradient.setStart(0, self.p_size / 2) self.m_label_gradient.setFinalStop(0, self.p_size + self.m_label_height + 5) self.m_label_gradient_rect = QRectF(self.p_size * 1 / 8, self.p_size / 2, self.p_size * 6 / 8, self.p_size + self.m_label_height + 5) self.update() def setPixmap(self, pixmap_id): if pixmap_id > 10: self.m_pixmap_n_str = str(pixmap_id) else: self.m_pixmap_n_str = "0%i" % pixmap_id self.m_pixmap.load(":/bitmaps/dial_%s%s.png" % (self.m_pixmap_n_str, "" if self.isEnabled() else "d")) if self.m_pixmap.width() > self.m_pixmap.height(): self.m_orientation = self.HORIZONTAL else: self.m_orientation = self.VERTICAL self.updateSizes() self.update() def minimumSizeHint(self): return QSize(self.p_size, self.p_size) def sizeHint(self): return QSize(self.p_size, self.p_size) def updateSizes(self): self.p_width = self.m_pixmap.width() self.p_height = self.m_pixmap.height() if self.p_width < 1: self.p_width = 1 if self.p_height < 1: self.p_height = 1 if self.m_orientation == self.HORIZONTAL: self.p_size = self.p_height self.p_count = self.p_width / self.p_height else: self.p_size = self.p_width self.p_count = self.p_height / self.p_width self.setMinimumSize(self.p_size, self.p_size + self.m_label_height + 5) self.setMaximumSize(self.p_size, self.p_size + self.m_label_height + 5) def enterEvent(self, event): self.m_hovered = True if self.m_hover_step == self.HOVER_MIN: self.m_hover_step = self.HOVER_MIN + 1 QDial.enterEvent(self, event) def leaveEvent(self, event): self.m_hovered = False if self.m_hover_step == self.HOVER_MAX: self.m_hover_step = self.HOVER_MAX - 1 QDial.leaveEvent(self, event) def paintEvent(self, event): painter = QPainter(self) painter.setRenderHint(QPainter.Antialiasing, True) if self.m_label: painter.setPen(self.m_color2) painter.setBrush(self.m_label_gradient) painter.drawRect(self.m_label_gradient_rect) painter.setPen(self.m_colorT[0] if self.isEnabled() else self.m_colorT[1]) painter.drawText(self.m_label_pos, self.m_label) if self.isEnabled(): current = float(self.value() - self.minimum()) divider = float(self.maximum() - self.minimum()) if divider == 0.0: return target = QRectF(0.0, 0.0, self.p_size, self.p_size) value = (current / divider) ## Regular knobs #else: per = int((self.p_count - 1) * (current / divider)) if self.m_orientation == self.HORIZONTAL: xpos = self.p_size * per ypos = 0.0 else: xpos = 0.0 ypos = self.p_size * per source = QRectF(xpos, ypos, self.p_size, self.p_size) painter.drawPixmap(target, self.m_pixmap, source) # Custom knobs (Dry/Wet and Volume) if self.m_custom_paint in (self.CUSTOM_PAINT_CARLA_WET, self.CUSTOM_PAINT_CARLA_VOL): # knob color colorGreen = QColor(0x5D, 0xE7, 0x3D, 191 + self.m_hover_step*7) colorBlue = QColor(0x3E, 0xB8, 0xBE, 191 + self.m_hover_step*7) #colorGreen = QColor(0x5D + self.m_hover_step*6, 0xE7 + self.m_hover_step*1, 0x3D + self.m_hover_step*5) #colorBlue = QColor(0x52 + self.m_hover_step*8, 0xEE + self.m_hover_step*1, 0xF8 + self.m_hover_step/2) # draw small circle ballPath = QPainterPath() ballRect = QRectF(8.0, 8.0, 15.0, 15.0) ballPath.addEllipse(ballRect) #painter.drawRect(ballRect) ballValue = (0.375 + 0.75*value) % 1.0 ballPoint = ballPath.pointAtPercent(ballValue) # draw arc startAngle = 216*16 spanAngle = -252.0*16*value if self.m_custom_paint == self.CUSTOM_PAINT_CARLA_WET: painter.setBrush(colorBlue) painter.setPen(QPen(colorBlue, 0)) painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.2, 2.2)) gradient = QConicalGradient(15.5, 15.5, -45) gradient.setColorAt(0.0, colorBlue) gradient.setColorAt(0.125, colorBlue) gradient.setColorAt(0.625, colorGreen) gradient.setColorAt(0.75, colorGreen) gradient.setColorAt(0.76, colorGreen) gradient.setColorAt(1.0, colorGreen) painter.setBrush(gradient) painter.setPen(QPen(gradient, 3)) else: painter.setBrush(colorBlue) painter.setPen(QPen(colorBlue, 0)) painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.2, 2.2)) painter.setBrush(colorBlue) painter.setPen(QPen(colorBlue, 3)) painter.drawArc(4.0, 4.0, 26.0, 26.0, startAngle, spanAngle) # Custom knobs (L and R) elif self.m_custom_paint in (self.CUSTOM_PAINT_CARLA_L, self.CUSTOM_PAINT_CARLA_R): # knob color color = QColor(0xAD + self.m_hover_step*5, 0xD5 + self.m_hover_step*4, 0x4B + self.m_hover_step*5) # draw small circle ballPath = QPainterPath() ballRect = QRectF(7.0, 8.0, 11.0, 12.0) ballPath.addEllipse(ballRect) #painter.drawRect(ballRect) ballValue = (0.375 + 0.75*value) % 1.0 ballPoint = ballPath.pointAtPercent(ballValue) painter.setBrush(color) painter.setPen(QPen(color, 0)) painter.drawEllipse(QRectF(ballPoint.x(), ballPoint.y(), 2.0, 2.0)) # draw arc if self.m_custom_paint == self.CUSTOM_PAINT_CARLA_L: startAngle = 216*16 spanAngle = -252.0*16*value elif self.m_custom_paint == self.CUSTOM_PAINT_CARLA_R: startAngle = 324.0*16 spanAngle = 252.0*16*(1.0-value) else: return painter.setPen(QPen(color, 2)) painter.drawArc(3.5, 4.5, 22.0, 22.0, startAngle, spanAngle) if self.HOVER_MIN < self.m_hover_step < self.HOVER_MAX: self.m_hover_step += 1 if self.m_hovered else -1 QTimer.singleShot(20, self, SLOT("update()")) elif not self.m_custom_paint: target = QRectF(0.0, 0.0, self.p_size, self.p_size) source = target painter.drawPixmap(target, self.m_pixmap, source) def resizeEvent(self, event): self.updateSizes() QDial.resizeEvent(self, event)
class OWLegendGradient(QGraphicsObject): gradient_width = 20 def __init__(self, palette, values, parent): QGraphicsObject.__init__(self, parent) self.parent = parent self.palette = palette self.values = values self.legend = parent self.label_items = [QGraphicsTextItem(text, self) for text in values] for i in self.label_items: i.setTextWidth(50) self.rect = QRectF() self.gradient_item = QGraphicsRectItem(self) self.gradient = QLinearGradient() self.gradient.setStops([(v * 0.1, self.palette[v * 0.1]) for v in range(11)]) self.orientation = Qt.Horizontal self.set_orientation(Qt.Vertical) def set_orientation(self, orientation): if self.orientation == orientation: return self.orientation = orientation if self.orientation == Qt.Vertical: height = max( [item.boundingRect().height() for item in self.label_items]) total_height = height * max(5, len(self.label_items)) interval = (total_height - self.label_items[-1].boundingRect().height()) / ( len(self.label_items) - 1) self.gradient_item.setRect(10, 0, self.gradient_width, total_height) self.gradient.setStart(10, 0) self.gradient.setFinalStop(10, total_height) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) y = 0 x = 30 for item in self.label_items: move_item_xy(item, x, y, self.parent.graph.animate_plot) y += interval self.rect = QRectF( 10, 0, self.gradient_width + max([item.boundingRect().width() for item in self.label_items]), self.label_items[0].boundingRect().height() * max(5, len(self.label_items))) else: width = 50 height = max( [item.boundingRect().height() for item in self.label_items]) total_width = width * max(5, len(self.label_items)) interval = (total_width - self.label_items[-1].boundingRect().width()) / ( len(self.label_items) - 1) self.gradient_item.setRect(0, 0, total_width, self.gradient_width) self.gradient.setStart(0, 0) self.gradient.setFinalStop(total_width, 0) self.gradient_item.setBrush(QBrush(self.gradient)) self.gradient_item.setPen(QPen(Qt.NoPen)) x = 0 y = 30 for item in self.label_items: move_item_xy(item, x, y, self.parent.graph.animate_plot) x += interval self.rect = QRectF(0, 0, total_width, self.gradient_width + height) def boundingRect(self): return getattr(self, 'rect', QRectF()) def paint(self, painter, option, widget): pass
def paintNormal(self, painter): """ Paints this item as the normal look. :param painter | <QPainter> """ # generate the rect rect = self.rect() x = 0 y = self.padding() #add scroll position to y #y = y+self._scrollBar.value() w = rect.width() h = rect.height() - (2 * self.padding()) - 1 radius = self.borderRadius() # grab the color options color = self.color() alt_color = self.alternateColor() if (self.isSelected()): color = self.highlightColor() alt_color = self.alternateHighlightColor() # create the background brush gradient = QLinearGradient() gradient.setStart(0, 0) gradient.setFinalStop(0, h) gradient.setColorAt(0, color) gradient.setColorAt(0.8, alt_color) gradient.setColorAt(1, color) painter.setPen(self.borderColor()) if (radius): painter.setRenderHint(painter.Antialiasing) pen = painter.pen() pen.setWidthF(0.5) painter.setPen(pen) painter.setBrush(QBrush(gradient)) painter.drawRoundedRect(x, y, w, h, radius, radius) # create the progress brush if (self.showProgress()): gradient = QLinearGradient() gradient.setStart(0, 0) gradient.setFinalStop(0, h) gradient.setColorAt(0, self.progressColor()) gradient.setColorAt(0.8, self.alternateProgressColor()) gradient.setColorAt(1, self.progressColor()) prog_w = (w - 4) * (self._percentComplete / 100.0) radius -= 2 painter.setPen(Qt.NoPen) painter.setBrush(QBrush(gradient)) painter.drawRoundedRect(x + 2, y + 2, prog_w, h - 4, radius, radius) # draw the text on this item if (self.text()): painter.setPen(self.textColor()) painter.drawText(x, y, w, h, Qt.AlignTop | Qt.AlignHCenter, self.text())
def paint(self, painter, option, widget): """ Draws this item with the inputed painter. :param painter | <QPainter> rect | <QRect> """ if self._dirty: self.rebuild() scene = self.scene() if not scene: return grid = scene.gridRect() typ = self.chartType() # draw the line chart if typ == XChartScene.Type.Line: painter.setRenderHint(painter.Antialiasing) # draw the path area area = self._buildData.get('path_area') if area and self.isShaded(): clr = QColor(self.color()) clr.setAlpha(120) painter.setPen(Qt.NoPen) painter.setBrush(clr) painter.drawPath(area) # draw the line data pen = QPen(self.color()) pen.setWidth(2) painter.setPen(pen) painter.setBrush(Qt.NoBrush) painter.drawPath(self.path()) if (self.showPointsInLine()): palette = QApplication.palette() pen = QPen(palette.color(palette.Base)) pen.setWidth(2) painter.setBrush(self.color()) painter.setPen(pen) for point in self._ellipses: painter.drawEllipse(point, self.pointRadius(), self.pointRadius()) # draw a bar chart elif typ == XChartScene.Type.Bar: painter.setRenderHint(painter.Antialiasing) pen = QPen(self.color()) pen.setWidth(1) painter.setPen(pen) for key, value, sub_path in self._subpaths: gradient = QLinearGradient() clr = QColor(self.color()) if (sub_path != self._hoveredPath): clr.setAlpha(130) gradient.setColorAt(0.0, clr.lighter(140)) gradient.setColorAt(0.1, clr.lighter(120)) gradient.setColorAt(0.25, clr.lighter(110)) gradient.setColorAt(1.0, clr.lighter(105)) if (self.orientation() == Qt.Horizontal): gradient.setStart(0, sub_path.boundingRect().top()) gradient.setFinalStop(0, sub_path.boundingRect().bottom()) else: gradient.setStart(sub_path.boundingRect().left(), 0) gradient.setFinalStop(sub_path.boundingRect().right(), 0) painter.setBrush(gradient) painter.drawPath(sub_path) # draw a simple pie chart (calculated by scene) elif typ == XChartScene.Type.Pie: painter.setRenderHint(painter.Antialiasing) center = self.pieCenter() radius = self.radius() for key, value, sub_path in self._subpaths: clr = self.keyColor(key) gradient = QRadialGradient(QPointF(0, 0), radius) a = QColor(clr.lighter(140)) b = QColor(clr.lighter(110)) a.setAlpha(40) b.setAlpha(80) # look for mouse over if (sub_path == self._hoveredPath): a.setAlpha(100) b.setAlpha(200) gradient.setColorAt(0, a) gradient.setColorAt(1, b) pen = QPen(clr) pen.setWidth(1) painter.setBrush(gradient) painter.setPen(pen) painter.drawPath(sub_path)
def draw(self, painter, size = None): """ :Arguments: painter : QPainter Opened painter on which to draw """ bounding_rect = QRectF() position = self.position transfer_function = self.transfer_function font = QFont(self.font) text_color = self.text_color line_color = self.line_color line_thickness = self.line_thickness value_range = self.value_range if size is None: viewport = painter.viewport() # viewport rectangle mat, ok = painter.worldMatrix().inverted() if not ok: raise ValueError("Transformation matrix of painter is singular.") viewport = mat.mapRect(viewport) else: viewport = size # First, prepare the gradient w = viewport.width() h = viewport.height() #print("Size of viewport: {0}x{1}".format(w, h)) gr = QLinearGradient() nb_values = ceil(w/5.0) brush_color = QColor() for i in range(int(nb_values)): brush_color.setRgbF(*transfer_function.rgba(i/nb_values)) gr.setColorAt(i/nb_values, brush_color) # Second, find its position metric = QFontMetricsF(font, painter.device()) font_test = [ str(i)*5 for i in range(10) ] lim_width = 0 lim_height = 0 for t in font_test: rect = metric.boundingRect(t) lim_width = max(lim_width, rect.width()) lim_height = max(lim_height, rect.height()) lim_height *= 3 length = self.scale_length shift_length = (1-length)/2 width = self.scale_width shift_width = self.scale_shift_width delta_value = value_range[1]-value_range[0] if position == "Top": scale_rect = QRectF(shift_length*w, shift_width*h, length*w, width*h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.left(), scale_rect.center().y()) gr.setFinalStop(scale_rect.right(), scale_rect.center().y()) start_pos = scale_rect.bottomLeft() end_pos = scale_rect.bottomRight() elif position == "Right": scale_rect = QRectF((1-shift_width-width)*w, shift_length*h, width*w, length*h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.center().x(), scale_rect.bottom()) gr.setFinalStop(scale_rect.center().x(), scale_rect.top()) start_pos = scale_rect.bottomLeft() end_pos = scale_rect.topLeft() elif position == "Bottom": scale_rect = QRectF(shift_length*w, (1-shift_width-width)*h, length*w, width*h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.left(), scale_rect.center().y()) gr.setFinalStop(scale_rect.right(), scale_rect.center().y()) start_pos = scale_rect.topLeft() end_pos = scale_rect.topRight() elif position == "Left": scale_rect = QRectF(shift_width*w, shift_length*h, width*w, length*h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.center().x(), scale_rect.bottom()) gr.setFinalStop(scale_rect.center().x(), scale_rect.top()) start_pos = scale_rect.bottomRight() end_pos = scale_rect.topRight() else: raise ValueError("Invalid scale position: %s" % position) shift_pos = (end_pos-start_pos)/delta_value if position in ["Left", "Right"]: is_vertical = True length = scale_rect.height() else: is_vertical = False length = scale_rect.width() # Get the ticks ticks = self.selectValues(length, is_vertical, painter) if len(ticks) == 0: return ticks_str, ticks_extra = self._tick2str(ticks) # Figure the shifts dist_to_bar = self.text_to_bar max_width = 0 max_height = 0 for t in ticks_str: rect = metric.boundingRect(t) max_width = max(rect.width(), max_width) max_height = max(rect.height(), max_height) if position == "Left": shift_left = dist_to_bar shift_top = None elif position == "Right": shift_left = -dist_to_bar-max_width shift_top = None elif position == "Top": shift_left = None shift_top = dist_to_bar else: shift_left = None shift_top = -dist_to_bar-max_height painter.save() painter.translate(viewport.topLeft()) #print("viewport.topLeft() = {0}x{1}".format(viewport.left(), viewport.top())) painter.setBrush(gr) line_pen = QPen(line_color) line_pen.setWidth(line_thickness) painter.setPen(line_pen) painter.drawRect(scale_rect) bounding_rect |= scale_rect #print("Scale rect: +{0}+{1}x{2}x{3}".format(scale_rect.left(), #scale_rect.top(), scale_rect.width(), scale_rect.height())) painter.setFont(font) painter.setPen(text_color) for ts,t in zip(ticks_str, ticks): r = metric.boundingRect(ts) pos = start_pos+shift_pos*(t-value_range[0]) if shift_left is None: pos.setX( pos.x() - r.width()/2 ) else: pos.setX( pos.x() + shift_left ) if shift_top is None: pos.setY( pos.y() - r.height()/2) else: pos.setY( pos.y() + shift_top ) r.moveTo(pos) real_rect = painter.drawText(r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, ts) bounding_rect |= real_rect if ticks_extra is not None or self.unit: unit = self.unit exp_width = width = space_width = 0 exp_txt = "" r = exp_r = unit_r = QRectF() exp_font = None if ticks_extra is not None: exp_txt = u"×10" r = metric.boundingRect(exp_txt) exp_font = QFont(font) exp_size = self.exp_size if exp_font.pixelSize() != -1: exp_font.setPixelSize(exp_size*exp_font.pixelSize()) else: exp_font.setPointSizeF(exp_size*exp_font.pointSizeF()) exp_metric = QFontMetricsF(exp_font, painter.device()) exp_r = exp_metric.boundingRect(ticks_extra) if unit: unit_r = metric.boundingRect(unit) total_width = r.width()+exp_r.width()+unit_r.width() total_height = max(r.height(),unit_r.height())+exp_r.height()/2 pos = scale_rect.topRight() log_debug("top right of scale bar = (%g,%g)" % (pos.x(), pos.y())) log_debug("Size of image = (%d,%d)" % (w,h)) log_debug("Size of text = (%g,%g)" % (total_width, total_height)) if position == "Bottom": pos.setY(pos.y() + scale_rect.height() + dist_to_bar) pos.setX(pos.x() - total_width) elif position == "Top": pos.setY(pos.y() - dist_to_bar - total_height) pos.setX(pos.x() - total_width) else: # position == "left" or "right" pos.setX(pos.x() - (scale_rect.width() + total_width)/2) if pos.x() < 0: pos.setX(dist_to_bar) elif pos.x()+total_width+dist_to_bar > w: pos.setX(w - total_width - dist_to_bar) pos.setY(pos.y() - dist_to_bar - total_height) log_debug("Display unit at position: (%g,%g)" % (pos.x(), pos.y())) if ticks_extra is not None: r.moveTo(pos) real_rect = painter.drawText(r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, exp_txt) bounding_rect |= real_rect pos.setX( pos.x() + r.width() ) pos.setY( pos.y() - metric.ascent()/2 ) exp_r.moveTo(pos) painter.setFont(exp_font) real_rect = painter.drawText(exp_r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, ticks_extra) bounding_rect |= real_rect pos.setY(pos.y() + metric.ascent()/2) if unit: pos.setX(pos.x() + space_width + exp_r.width()) unit_r.moveTo(pos) painter.setFont(font) real_rect = painter.drawText(unit_r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, unit) bounding_rect |= real_rect # Draw the ticks now painter.setPen(line_pen) tick_size = self.tick_size if is_vertical: width = scale_rect.width()*tick_size else: width = scale_rect.height()*tick_size pen_width = painter.pen().widthF() if pen_width == 0: pen_width = 1.0 for t in ticks: pos1 = start_pos + shift_pos*(t-value_range[0]) pos2 = QPointF(pos1) if is_vertical: pos1.setX(scale_rect.left() + pen_width) pos2.setX(pos1.x() + width - pen_width) painter.drawLine(pos1, pos2) pos1.setX(scale_rect.right() - pen_width) pos2.setX(pos1.x() - width + pen_width) painter.drawLine(pos1, pos2) else: pos1.setY(scale_rect.top() + pen_width) pos2.setY(pos1.y() + width - pen_width) painter.drawLine(pos1, pos2) pos1.setY(scale_rect.bottom() - pen_width) pos2.setY(pos1.y() - width + pen_width) painter.drawLine(pos1, pos2) painter.restore() bounding_rect = bounding_rect.adjusted(-pen_width, -pen_width, pen_width, pen_width) return bounding_rect
def draw(self, painter, size=None): """ :Arguments: painter : QPainter Opened painter on which to draw """ bounding_rect = QRectF() position = self.position transfer_function = self.transfer_function font = QFont(self.font) text_color = self.text_color line_color = self.line_color line_thickness = self.line_thickness value_range = self.value_range if size is None: viewport = painter.viewport() # viewport rectangle mat, ok = painter.worldMatrix().inverted() if not ok: raise ValueError( "Transformation matrix of painter is singular.") viewport = mat.mapRect(viewport) else: viewport = size # First, prepare the gradient w = viewport.width() h = viewport.height() #print("Size of viewport: {0}x{1}".format(w, h)) gr = QLinearGradient() nb_values = ceil(w / 5.0) brush_color = QColor() for i in range(int(nb_values)): brush_color.setRgbF(*transfer_function.rgba(i / nb_values)) gr.setColorAt(i / nb_values, brush_color) # Second, find its position metric = QFontMetricsF(font, painter.device()) font_test = [str(i) * 5 for i in range(10)] lim_width = 0 lim_height = 0 for t in font_test: rect = metric.boundingRect(t) lim_width = max(lim_width, rect.width()) lim_height = max(lim_height, rect.height()) lim_height *= 3 length = self.scale_length shift_length = (1 - length) / 2 width = self.scale_width shift_width = self.scale_shift_width delta_value = value_range[1] - value_range[0] if position == "Top": scale_rect = QRectF(shift_length * w, shift_width * h, length * w, width * h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.left(), scale_rect.center().y()) gr.setFinalStop(scale_rect.right(), scale_rect.center().y()) start_pos = scale_rect.bottomLeft() end_pos = scale_rect.bottomRight() elif position == "Right": scale_rect = QRectF((1 - shift_width - width) * w, shift_length * h, width * w, length * h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.center().x(), scale_rect.bottom()) gr.setFinalStop(scale_rect.center().x(), scale_rect.top()) start_pos = scale_rect.bottomLeft() end_pos = scale_rect.topLeft() elif position == "Bottom": scale_rect = QRectF(shift_length * w, (1 - shift_width - width) * h, length * w, width * h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.left(), scale_rect.center().y()) gr.setFinalStop(scale_rect.right(), scale_rect.center().y()) start_pos = scale_rect.topLeft() end_pos = scale_rect.topRight() elif position == "Left": scale_rect = QRectF(shift_width * w, shift_length * h, width * w, length * h) limit_rect(scale_rect, viewport, lim_width, lim_height) gr.setStart(scale_rect.center().x(), scale_rect.bottom()) gr.setFinalStop(scale_rect.center().x(), scale_rect.top()) start_pos = scale_rect.bottomRight() end_pos = scale_rect.topRight() else: raise ValueError("Invalid scale position: %s" % position) shift_pos = (end_pos - start_pos) / delta_value if position in ["Left", "Right"]: is_vertical = True length = scale_rect.height() else: is_vertical = False length = scale_rect.width() # Get the ticks ticks = self.selectValues(length, is_vertical, painter) if len(ticks) == 0: return ticks_str, ticks_extra = self._tick2str(ticks) # Figure the shifts dist_to_bar = self.text_to_bar max_width = 0 max_height = 0 for t in ticks_str: rect = metric.boundingRect(t) max_width = max(rect.width(), max_width) max_height = max(rect.height(), max_height) if position == "Left": shift_left = dist_to_bar shift_top = None elif position == "Right": shift_left = -dist_to_bar - max_width shift_top = None elif position == "Top": shift_left = None shift_top = dist_to_bar else: shift_left = None shift_top = -dist_to_bar - max_height painter.save() painter.translate(viewport.topLeft()) #print("viewport.topLeft() = {0}x{1}".format(viewport.left(), viewport.top())) painter.setBrush(gr) line_pen = QPen(line_color) line_pen.setWidth(line_thickness) painter.setPen(line_pen) painter.drawRect(scale_rect) bounding_rect |= scale_rect #print("Scale rect: +{0}+{1}x{2}x{3}".format(scale_rect.left(), #scale_rect.top(), scale_rect.width(), scale_rect.height())) painter.setFont(font) painter.setPen(text_color) for ts, t in zip(ticks_str, ticks): r = metric.boundingRect(ts) pos = start_pos + shift_pos * (t - value_range[0]) if shift_left is None: pos.setX(pos.x() - r.width() / 2) else: pos.setX(pos.x() + shift_left) if shift_top is None: pos.setY(pos.y() - r.height() / 2) else: pos.setY(pos.y() + shift_top) r.moveTo(pos) real_rect = painter.drawText( r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, ts) bounding_rect |= real_rect if ticks_extra is not None or self.unit: unit = self.unit exp_width = width = space_width = 0 exp_txt = "" r = exp_r = unit_r = QRectF() exp_font = None if ticks_extra is not None: exp_txt = u"×10" r = metric.boundingRect(exp_txt) exp_font = QFont(font) exp_size = self.exp_size if exp_font.pixelSize() != -1: exp_font.setPixelSize(exp_size * exp_font.pixelSize()) else: exp_font.setPointSizeF(exp_size * exp_font.pointSizeF()) exp_metric = QFontMetricsF(exp_font, painter.device()) exp_r = exp_metric.boundingRect(ticks_extra) if unit: unit_r = metric.boundingRect(unit) total_width = r.width() + exp_r.width() + unit_r.width() total_height = max(r.height(), unit_r.height()) + exp_r.height() / 2 pos = scale_rect.topRight() log_debug("top right of scale bar = (%g,%g)" % (pos.x(), pos.y())) log_debug("Size of image = (%d,%d)" % (w, h)) log_debug("Size of text = (%g,%g)" % (total_width, total_height)) if position == "Bottom": pos.setY(pos.y() + scale_rect.height() + dist_to_bar) pos.setX(pos.x() - total_width) elif position == "Top": pos.setY(pos.y() - dist_to_bar - total_height) pos.setX(pos.x() - total_width) else: # position == "left" or "right" pos.setX(pos.x() - (scale_rect.width() + total_width) / 2) if pos.x() < 0: pos.setX(dist_to_bar) elif pos.x() + total_width + dist_to_bar > w: pos.setX(w - total_width - dist_to_bar) pos.setY(pos.y() - dist_to_bar - total_height) log_debug("Display unit at position: (%g,%g)" % (pos.x(), pos.y())) if ticks_extra is not None: r.moveTo(pos) real_rect = painter.drawText( r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, exp_txt) bounding_rect |= real_rect pos.setX(pos.x() + r.width()) pos.setY(pos.y() - metric.ascent() / 2) exp_r.moveTo(pos) painter.setFont(exp_font) real_rect = painter.drawText( exp_r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, ticks_extra) bounding_rect |= real_rect pos.setY(pos.y() + metric.ascent() / 2) if unit: pos.setX(pos.x() + space_width + exp_r.width()) unit_r.moveTo(pos) painter.setFont(font) real_rect = painter.drawText( unit_r, Qt.TextDontClip | Qt.AlignVCenter | Qt.AlignHCenter, unit) bounding_rect |= real_rect # Draw the ticks now painter.setPen(line_pen) tick_size = self.tick_size if is_vertical: width = scale_rect.width() * tick_size else: width = scale_rect.height() * tick_size pen_width = painter.pen().widthF() if pen_width == 0: pen_width = 1.0 for t in ticks: pos1 = start_pos + shift_pos * (t - value_range[0]) pos2 = QPointF(pos1) if is_vertical: pos1.setX(scale_rect.left() + pen_width) pos2.setX(pos1.x() + width - pen_width) painter.drawLine(pos1, pos2) pos1.setX(scale_rect.right() - pen_width) pos2.setX(pos1.x() - width + pen_width) painter.drawLine(pos1, pos2) else: pos1.setY(scale_rect.top() + pen_width) pos2.setY(pos1.y() + width - pen_width) painter.drawLine(pos1, pos2) pos1.setY(scale_rect.bottom() - pen_width) pos2.setY(pos1.y() - width + pen_width) painter.drawLine(pos1, pos2) painter.restore() bounding_rect = bounding_rect.adjusted(-pen_width, -pen_width, pen_width, pen_width) return bounding_rect