Beispiel #1
0
 def drawRoundedFrame(self, painter, rect, xRadius, yRadius, palette,
                      lineWidth, frameStyle):
     """
     Draw a rectangular frame with rounded borders
     
     :param QPainter painter: Painter
     :param QRectF rect: Frame rectangle
     :param float xRadius: x-radius of the ellipses defining the corners
     :param float yRadius: y-radius of the ellipses defining the corners
     :param QPalette palette: `QPalette.WindowText` is used for plain borders, `QPalette.Dark` and `QPalette.Light` for raised or sunken borders
     :param int lineWidth: Line width
     :param int frameStyle: bitwise OR´ed value of `QFrame.Shape` and `QFrame.Shadow`
     """
     painter.save()
     painter.setRenderHint(QPainter.Antialiasing, True)
     painter.setBrush(Qt.NoBrush)
     lw2 = lineWidth * 0.5
     r = rect.adjusted(lw2, lw2, -lw2, -lw2)
     path = QPainterPath()
     path.addRoundedRect(r, xRadius, yRadius)
     Plain, Sunken, Raised = list(range(3))
     style = Plain
     if (frameStyle & QFrame.Sunken) == QFrame.Sunken:
         style = Sunken
     if (frameStyle & QFrame.Raised) == QFrame.Raised:
         style = Raised
     if style != Plain and path.elementCount() == 17:
         pathList = [QPainterPath() for _i in range(8)]
         for i in range(4):
             j = i * 4 + 1
             pathList[2 * i].moveTo(
                 path.elementAt(j - 1).x,
                 path.elementAt(j - 1).y)
             pathList[2 * i].cubicTo(
                 path.elementAt(j + 0).x,
                 path.elementAt(j + 0).y,
                 path.elementAt(j + 1).x,
                 path.elementAt(j + 1).y,
                 path.elementAt(j + 2).x,
                 path.elementAt(j + 2).y,
             )
             pathList[2 * i + 1].moveTo(
                 path.elementAt(j + 2).x,
                 path.elementAt(j + 2).y)
             pathList[2 * i + 1].lineTo(
                 path.elementAt(j + 3).x,
                 path.elementAt(j + 3).y)
         c1 = QColor(palette.color(QPalette.Dark))
         c2 = QColor(palette.color(QPalette.Light))
         if style == Raised:
             c1, c2 = c2, c1
         for i in range(5):
             r = pathList[2 * i].controlPointRect()
             arcPen = QPen()
             arcPen.setCapStyle(Qt.FlatCap)
             arcPen.setWidth(lineWidth)
             linePen = QPen()
             linePen.setCapStyle(Qt.FlatCap)
             linePen.setWidth(lineWidth)
             if i == 0:
                 arcPen.setColor(c1)
                 linePen.setColor(c1)
             elif i == 1:
                 gradient = QLinearGradient()
                 gradient.setStart(r.topLeft())
                 gradient.setFinalStop(r.bottomRight())
                 gradient.setColorAt(0.0, c1)
                 gradient.setColorAt(1.0, c2)
                 arcPen.setBrush(gradient)
                 linePen.setColor(c2)
             elif i == 2:
                 arcPen.setColor(c2)
                 linePen.setColor(c2)
             elif i == 3:
                 gradient = QLinearGradient()
                 gradient.setStart(r.bottomRight())
                 gradient.setFinalStop(r.topLeft())
                 gradient.setColorAt(0.0, c2)
                 gradient.setColorAt(1.0, c1)
                 arcPen.setBrush(gradient)
                 linePen.setColor(c1)
             painter.setPen(arcPen)
             painter.drawPath(pathList[2 * i])
             painter.setPen(linePen)
             painter.drawPath(pathList[2 * i + 1])
     else:
         pen = QPen(palette.color(QPalette.WindowText), lineWidth)
         painter.setPen(pen)
         painter.drawPath(path)
     painter.restore()
Beispiel #2
0
class _GradientLegend(GraphicsWidget):
    """Class to make GradientLegend a GraphicsWidget.

    Draws a color gradient rectangle along with text labels denoting the value
    at specific points along the gradient.

    Parameters
    ----------
    size : list of int, optional
        Size of the widget within the GraphicsWidget rectangle.
    colors : a list of RGB codes, optional
        The lookup table to be used to design the gradient.
    labels : dict of keys = strings and values = int
        The labels that will appear along the colorbar.
        The values determine the sequence of labels in descending order.
    minVal : int, optional
        If labels is None, so only minVal and maxVal are displayed in the
        beggining and in the end of the colorbar.
    maxVal : int, optional
        If labels is None, so only minVal and maxVal are displayed in the
        beggining and in the end of the colorbar.
    """
    def __init__(self,
                 size=None,
                 colors=None,
                 labels=None,
                 minVal=None,
                 maxVal=None):
        GraphicsWidget.__init__(self)
        self.setAcceptedMouseButtons(Qt.NoButton)
        self.size = size

        # if min and max values are None, assume normalized data
        self.minVal = 0 if minVal is None else minVal
        self.maxVal = 1 if maxVal is None else maxVal
        self.labels = {1: 'min', 0: 'max'} if labels is None else labels
        self.label_format = '{: .3f}'
        self.gradient = QLinearGradient()
        if colors is None:
            self.colors = [[0, 0, 0], [255, 0, 0]]
        else:
            self.colors = colors
        self.setIntColorScale(colors=self.colors,
                              minVal=self.minVal,
                              maxVal=self.maxVal,
                              labels=self.labels)

    def setIntColorScale(self, colors, minVal=None, maxVal=None, labels=None):
        # generate color gradient
        g = QLinearGradient()
        for i in range(len(colors)):
            x = float(i) / len(colors)
            g.setColorAt(x, QColor(colors[i][0], colors[i][1], colors[i][2]))
        self._setGradient(g)

        # add labels
        if labels is None and (minVal is None or maxVal is None):
            self.setLabels(self.labels)
        elif labels is None:
            self.setLabels({1: str(minVal), 0: str(maxVal)})
        else:
            self.setLabels(labels)

    def _setGradient(self, g):
        self.gradient = g
        self.update()

    def setLimits(self, data):
        minVal = data[0]
        maxVal = data[1]
        if minVal == self.minVal and maxVal == self.maxVal:
            return
        self.minVal = minVal
        self.maxVal = maxVal
        for k in self.labels.keys():
            newv = minVal + (1 - k) * (maxVal - minVal)
            newv = self.label_format.format(newv)
            self.labels[k] = newv
        self.setLabels(self.labels)

    def setLabels(self, l):
        """
        Define labels to appear next to the color scale.

        Accepts a dict of {text: value} pairs.
        """
        self.labels = l
        self.update()

    def paint(self, p, opt, widget):
        GraphicsWidget.paint(self, p, opt, widget)
        rect = self.boundingRect()  # Boundaries of visible area in scene coord
        size = self.size if self.size is not None \
            else [rect.right()-rect.left(), rect.bottom() - rect.top()]

        # determine max width of all labels
        textPadding = 2  # in px
        labelWidth = 0
        labelHeight = 0
        for val in self.labels.values():
            b = p.boundingRect(QRectF(0, 0, 0, 0),
                               Qt.AlignLeft | Qt.AlignVCenter, str(val))
            labelWidth = max(labelWidth, b.width())
            labelHeight = max(labelHeight, b.height())

        x1_back = (rect.right() - rect.left() - size[0]) / 2
        x2_back = (rect.right() - rect.left() + size[0]) / 2
        y1_back = (rect.bottom() - rect.top() - size[1]) / 2
        y2_back = (rect.bottom() - rect.top() + size[1]) / 2

        x1_grad = x1_back + textPadding * 2
        x2_grad = x2_back - (labelWidth + textPadding * 2)
        y1_grad = y1_back + (labelHeight / 2 + textPadding)
        y2_grad = y2_back - (labelHeight / 2 + textPadding)

        # Draw background
        p.setPen(QPen(QColor(0, 0, 0, 0)))
        p.setBrush(QBrush(QColor(255, 255, 255, 0)))
        rect = QRectF(QPointF(x1_back, y1_back), QPointF(x2_back, y2_back))
        p.drawRect(rect)

        # Draw color bar
        self.gradient.setStart(0, y2_grad)
        self.gradient.setFinalStop(0, y1_grad)
        p.setPen(QPen(QColor(0, 0, 0)))
        p.setBrush(self.gradient)
        rect = QRectF(QPointF(x1_grad, y1_grad), QPointF(x2_grad, y2_grad))
        p.drawRect(rect)

        # draw labels
        tx = x2_grad + textPadding * 2
        lw = labelWidth
        lh = labelHeight
        for key, val in self.labels.items():
            y = y1_grad + key * (y2_grad - y1_grad)
            p.drawText(QRectF(tx, y - lh / 2.0, lw, lh),
                       Qt.AlignLeft | Qt.AlignVCenter, str(val))

        self.setMinimumWidth(labelWidth + 2 * textPadding + 20)