コード例 #1
0
ファイル: Blackversion.py プロジェクト: midenko-gb/pra1
class DynamicSpline(QChart):
    def __init__(self):
        super().__init__()
        self.m_step = 0
        self.m_x = 2
        self.m_y = 1
        # Инициализировать изображение
        self.series = QSplineSeries(self)
        red_pen = QPen(Qt.red)
        red_pen.setWidth(2)
        self.series.setPen(red_pen)
        self.axisX = QValueAxis()
        self.axisY = QValueAxis()
        self.series.append(self.m_x, self.m_y)

        self.addSeries(self.series)
        self.addAxis(self.axisX, Qt.AlignBottom)
        self.addAxis(self.axisY, Qt.AlignLeft)
        self.series.attachAxis(self.axisX)
        self.series.attachAxis(self.axisY)
        self.axisX.setTickCount(5)
        self.axisX.setRange(0, 10)
        self.axisY.setRange(0, 100)

        self.timer = QTimer(self)
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.handleTimeout)
        self.timer.start()


    def handleTimeout(self):
        x = self.plotArea().width() / self.axisX.tickCount()
        y = (self.axisX.max() - self.axisX.min()) / self.axisX.tickCount()
        self.m_x += y

        # В PyQt 5.11.3 и выше, QRandomGenerator.global() был переименован в global_()
        try:
            self.m_y=db_wrk()
        except :
            self.m_y = QRandomGenerator.global_().bounded(50)
        self.series.append(self.m_x, self.m_y)
        self.scroll(x, 0)
        if self.m_x >= 10:
            self.timer.stop()

    def db_wrk():

        return m_y
コード例 #2
0
ファイル: chart.py プロジェクト: kindoblue/QtChartExample
class Chart(QChart):

    def __init__(self):
        super(QChart, self).__init__()

        self.m_timer = QTimer()
        self.m_series = None
        self.m_titles = []
        self.m_axis = QValueAxis()
        self.m_step = None
        self.m_x = 5
        self.m_y = 1

        random.seed(QTime.currentTime().msec())

        self.m_timer.timeout.connect(self.handleTimeout)
        self.m_timer.setInterval(1000)

        self.m_series = QSplineSeries(self)
        green = QPen(Qt.green)
        green.setWidth(3)
        self.m_series.setPen(green)
        self.m_series.append(self.m_x, self.m_y)

        self.addSeries(self.m_series)
        self.createDefaultAxes()
        self.setAxisX(self.m_axis, self.m_series)
        self.m_axis.setTickCount(5)
        self.axisX().setRange(0, 10)
        self.axisY().setRange(-5, 10)

        self.m_timer.start()


    @pyqtSlot()
    def handleTimeout(self):
        x = self.plotArea().width() / self.m_axis.tickCount()
        y = (self.m_axis.max() - self.m_axis.min()) / self.m_axis.tickCount()
        self.m_x += y
        self.m_y = random.randint(0, 5) - 2.5
        self.m_series.append(self.m_x, self.m_y)
        self.scroll(x, 0)
        if self.m_x is 100:
            self.m_timer.stop()
コード例 #3
0
class DynamicSpline(QChart):
    def __init__(self):
        super().__init__()
        self.m_step = 0
        self.m_x = 5
        self.m_y = 1
        # 初始化图像
        self.series = QSplineSeries(self)
        green_pen = QPen(Qt.red)
        green_pen.setWidth(3)
        self.series.setPen(green_pen)
        self.axisX = QValueAxis()
        self.axisY = QValueAxis()
        self.series.append(self.m_x, self.m_y)

        self.addSeries(self.series)
        self.addAxis(self.axisX, Qt.AlignBottom)
        self.addAxis(self.axisY, Qt.AlignLeft)
        self.series.attachAxis(self.axisX)
        self.series.attachAxis(self.axisY)
        self.axisX.setTickCount(5)
        self.axisX.setRange(0, 10)
        self.axisY.setRange(-5, 10)

        self.timer = QTimer(self)
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.handleTimeout)
        self.timer.start()

    def handleTimeout(self):
        x = self.plotArea().width() / self.axisX.tickCount()
        y = (self.axisX.max() - self.axisX.min()) / self.axisX.tickCount()
        self.m_x += y
        # 在PyQt5.11.3及以上版本中,QRandomGenerator.global()被重命名为global_()
        self.m_y = QRandomGenerator.global_().bounded(5) - 2.5
        self.series.append(self.m_x, self.m_y)
        self.scroll(x, 0)
        if self.m_x >= 100:
            self.timer.stop()
コード例 #4
0
class XChartProbit(QChart):
    def __init__(self, parent=None):
        super(QChart, self).__init__(parent)

        # Class Vars
        self.activeDistr = 'lognorm'
        self.knowndistr = distr._distrnames()
        self.data = dict()

        # Axis Setup
        self.axisX = QValueAxis()
        self.axisY = QValueAxis()

        self.axisX.setLabelsVisible(False)
        self.axisX.setTickCount(2)
        self.axisX.setTitleText("Series Fractional Probability")
        self.axisY.setTitleText("Value")
        self.setAxesMinMax(-3, 3, 0.01, 1.5)

        self.axisX.setMinorGridLineVisible(False)
        self.axisX.setGridLineVisible(False)

        # define the default grid colour to grey
        self.setGridColor(110, 110, 110)

        self.setActiveProbit(self.activeDistr)
        self.plotAreaChanged.connect(self.onPlotSizeChanged)
        # method needed for axes change to redraw grid lines

    def addLinearReg(self, seriesname):
        x = self.data[seriesname]['X'], y = self.data[seriesname][seriesname]
        # adds a linear regression line for a data set x,y
        slope, intercept, r_value, p_value, std_err = linregress(x, y)
        xmin = distr.distrppf(self.activeDistr, 0.01)
        xmax = distr.distrppf(self.activeDistr, 0.99)
        ymin = slope * xmin + intercept
        ymax = slope * xmax + intercept
        data = dict()
        data['X'] = [xmin, xmax]
        data['LinearReg'] = [ymin, ymax]
        lines = XLineSeries(data, xkey='X', openGL=True)

        self.addSeries(lines[0])
        self.setAxes(lines[0])

    def loadSeries(self, arr, name):
        # takes a list/array arr
        y = array(arr).copy()
        y.sort()
        self.data[name] = y
        self.redrawChart()

    def plotSeries(self, name):
        nsamp = len(self.data[name])
        # add data to temport dictionary
        tdict = dict()
        if self.activeScale == 'log10':
            tdict[name] = log10(self.data[name])
        elif self.activeScale == 'linear':
            tdict[name] = self.data[name]
        tdict['X'] = distr.distrppf(self.activeProbit, [
            percentileofscore(self.data[name], self.data[name][i]) / 100.00001
            for i in range(0, nsamp)
        ])
        series = XScatterSeries(tdict, xkey='X', openGL=True)
        self.addSeries(series[0])
        self.setAxes(series[0])

    def _replotData(self):
        for key in self.data.keys():
            self.pl

    def axesMinMax(self):
        # returns a length 4 list of the axes min and max values [x1,x2,y1,y2]
        return [
            self.axisX.min(),
            self.axisX.max(),
            self.axisY.min(),
            self.axisY.max()
        ]

    def redrawChart(self):
        self.removeAllSeries()
        self._removeHorizontalGridLabels()
        self.resetAxes()
        self._drawVerticalGridLines()
        if self.activeScale == 'log10':
            self.axisY.setLabelsVisible(False)
            self.axisY.setTickCount(1)
            self.setTitle("Log Probit Plot")
            self.axisY.setMinorGridLineVisible(False)
            self.axisY.setGridLineVisible(False)
            self._drawHorizontalGridLine()
            self._drawHorizontalLabels()
            self._drawHorizontalGridlLabels()
        elif self.activeScale == 'linear':
            self.axisY.setLabelsVisible(True)
            self.axisY.setTickCount(10)
            self.setTitle("Probit Plot")
            self.axisY.setMinorGridLineVisible(True)
            self.axisY.setGridLineVisible(True)

        for serkey in self.data.keys():
            self.plotSeries(serkey)

    def resetAxes(self):
        ymins = []
        ymaxs = []
        for key in self.data.keys():
            ymins.append(min(self.data[key]))
            ymaxs.append(max(self.data[key]))
        try:
            ymin = min(ymins)
            ymax = max(ymaxs)
        except ValueError:
            ymin = 1.1
            ymax = 2

        xmin = distr.distrppf(self.activeProbit, 0.001)
        xmax = distr.distrppf(self.activeProbit, 0.999)
        if self.activeScale == 'linear':
            yscal = 0.1 * (ymax - ymin)
            self.setAxesMinMax(xmin, xmax, ymin - yscal, ymax + yscal)
        elif self.activeScale == 'log10':
            yscal = 0.1 * (log10(ymax) - log10(ymin))
            self.setAxesMinMax(xmin, xmax, log10(ymin), log10(ymax))
            #self.setAxesMinMax(xmin,xmax,log10(ymin)-yscal,log10(ymax)+yscal*0.1)

    def setGridColor(self, r, g, b):
        # sets the colour of the background grid
        self.gridcolor = QColor(r, g, b)

    def setActiveProbit(self, type):
        if type in self.knowndistr:
            self.activeDistr = type
            if type == 'norm':
                self.activeProbit = 'norm'
                self.activeScale = 'linear'
            elif type == 'lognorm':
                self.activeProbit = 'norm'
                self.activeScale = 'log10'
        #self.redrawChart()

    def setActiveScale(self, newscale):
        self.activeScale = newscale

    def setAxes(self, series):
        # assigns a series to the chart default axes
        self.setAxisX(self.axisX, series)
        self.setAxisY(self.axisY, series)

    def setAxesMinMax(self, x1, x2, y1, y2):
        # sets the min max values in X and Y
        self.axisX.setMin(x1)
        self.axisX.setMax(x2)
        self.axisY.setMin(y1)
        self.axisY.setMax(y2)

    def _drawHorizontalLabels(self):
        xmin = self.axisX.min()
        xmax = self.axisX.max()
        axisScale = 1 / (xmax - xmin
                         )  # scaler for plotted axis (reduces to 0-1.0)
        # calculate probit values to scale from grid lines insert min and max values to scale correctly
        vlabx = distr.distrppf(self.activeProbit, self.vgridx)
        vlabx = insert(vlabx, 0, xmin)
        vlabx = insert(vlabx, len(vlabx), xmax)
        vlabx = (
            vlabx - xmin
        ) * axisScale  #scale the probit value to ratios of the Xaxis length
        paw = self.plotArea().width()
        pah = self.plotArea().height()  #find the plot width and height
        # find plot bottom left corner X and Y
        pblx = self.plotArea().bottomLeft().x()
        pbly = self.plotArea().bottomLeft().y()
        # offset from axix by 10 pixels -> may need to automate this offset in future
        pbly_lab = pbly + 10
        # calculate the position on the chart in x plane with which to place each label.
        pblx = [pblx + int(paw * x) for x in vlabx[1:-1]]
        try:
            self.hlabels
        except AttributeError:
            self.hlabels = []
            for i, labx in enumerate(
                    pblx):  #run through labels and create and position them
                # label text based on P scale
                ltext = 'P' + '%02d' % round(100.0 * (1.0 - self.vgridx[i]))
                self.hlabels.append(self.scene().addText(ltext))

        for i, labx in enumerate(
                pblx):  #run through labels and create and position them
            self.hlabels[i].setPos(
                labx - 0.5 * self.hlabels[i].boundingRect().width(),
                pbly)  #centre on tick marks

    def _drawVerticalGridLines(self):
        self.vgridx = arange(0.05, 1.0, 0.05)
        self.vgridx = insert(self.vgridx, 0, [0.01, 0.02])
        self.vgridx = insert(self.vgridx, len(self.vgridx), [0.98, 0.99])
        vgridy = [self.axisY.min(), self.axisY.max()]
        self.vgridseries = []
        for val in self.vgridx:
            line = 'P' + '%02d' % round(100.0 * (1.0 - val))
            tdict = {
                'X': [distr.distrppf(self.activeProbit, val)] * 2,
                line: vgridy
            }
            self.vgridseries = self.vgridseries + XLineSeries(
                tdict, xkey='X', openGL=True)
        for i, line in enumerate(self.vgridseries):
            pen = line.pen()
            pen.setColor(self.gridcolor)
            pen.setWidthF(0.4), line.setPen(pen)
            line.setPointLabelsVisible(True)
            self.addSeries(line)
            self.setAxes(line)
            self.legend().markers(line)[0].setVisible(False)

    def _drawHorizontalGridLine(self):
        # calculate xmin and xmax points for lines to completely cross graph
        hgridx = [
            distr.distrppf(self.activeProbit, 0.0001) - 1,
            distr.distrppf(self.activeProbit, 0.9999) + 1
        ]
        # calculate log scale for lines y values
        self.hgridy = self._logrange(10**self.axisY.min(),
                                     10**self.axisY.max(),
                                     base=10)
        self.hgridseries = []
        # create a line series for each lines and add to list
        for val in self.hgridy:
            line = '%d' % val
            tdict = {'X': hgridx, line: [log10(val)] * 2}
            self.hgridseries = self.hgridseries + XLineSeries(
                tdict, xkey='X', openGL=True)
        # add each of the series to the grid with special formatting
        for i, line in enumerate(self.hgridseries):
            pen = line.pen()
            pen.setColor(self.gridcolor)
            pen.setWidthF(0.4), line.setPen(pen)
            self.addSeries(line)
            self.setAxes(line)
            self.legend().markers(line)[0].setVisible(False)

    def _drawHorizontalGridlLabels(self):
        ymin = self.axisY.min()
        ymax = self.axisY.max()
        axisScale = 1 / (ymax - ymin
                         )  # scaler for plotted axis (reduces to 0-1.0)
        # calculate base10 values to scale from grid lines insert min and max values to scale correctly
        vlaby = log10(self.hgridy)
        vlaby = insert(vlaby, 0, ymin)
        vlaby = insert(vlaby, len(vlaby), ymax)
        vlaby = (
            vlaby - ymin
        ) * axisScale  # scale the probit value to ratios of the Xaxis length
        paw = self.plotArea().width()
        pah = self.plotArea().height()  # find the plot width and height
        # find plot bottom left corner X and Y
        pblx = self.plotArea().bottomLeft().x()
        pbly = self.plotArea().bottomLeft().y()
        # offset from axix by 10 pixels -> may need to automate this offset in future
        pblx_lab = pblx - 10
        # calculate the position on the chart in y plane with which to place each label.
        pbly = [pbly - int(pah * y) for y in vlaby[1:-1]]
        self.vlabels = []
        for i, labx in enumerate(
                pbly):  # run through labels and create and position them
            # label text based on P scale
            ltext = str(self.hgridy[i])
            self.vlabels.append(self.scene().addText(ltext))

        for i, laby in enumerate(
                pbly):  #run through labels and create and position them
            # label text based on P scale
            self.vlabels[i].setPos(
                pblx - self.vlabels[i].boundingRect().width() - 10,
                laby - 0.5 *
                self.vlabels[i].boundingRect().height())  #centre on tick marks

    def _removeHorizontalGridLine(self):
        for ser in self.hgridseries:
            self.removeSeries(ser)

    def _removeVerticalGridLine(self):
        for ser in self.vgridseries:
            self.removeSeries(ser)

    def _removeHorizontalGridLabels(self):
        try:
            for lab in self.vlabels:
                self.scene().removeItem(lab)
        except AttributeError:
            pass

    def _logrange(self, min, max, base=10):
        if min <= 0:
            min += max / (base**10)
        y = 1
        bpow = base
        if min < base:
            while min < bpow:
                y -= 1
                bpow = pow(base, y)
        else:
            while min > bpow:
                y += 1
                bpow = pow(base, y)
        out = array([])
        while bpow < max:
            y += 1
            bpown = pow(base, y)
            out = append(out, arange(bpow, bpown, bpow))
            bpow = bpown
        i = 0
        j = 0
        for ind, val in enumerate(out):
            if val <= min:
                i = ind
            if val <= max:
                j = ind
        return out[i:j + 1]

    @pyqtSlot()
    def onPlotSizeChanged(self):
        #reset position of labels
        self.redrawChart()
コード例 #5
0
class VCTemporalSeries(VCCommons):
    def __init__(self):
        VCCommons.__init__(self)
        self.__chart = QChart()  #After setChart you must call it with chart()
        self.customContextMenuRequested.connect(
            self.on_customContextMenuRequested)
        self._allowHideSeries = True

        #Axis cration
        self.axisX = QDateTimeAxis()
        self.axisX.setTickCount(8)
        self.axisX.setFormat("yyyy-MM")
        self.maxx = None
        self.maxy = None
        self.minx = None
        self.miny = None

        self.__ohclduration = eOHCLDuration.Day
        self.axisY = QValueAxis()
        self.axisY.setLabelFormat("%i")

        self.setRenderHint(QPainter.Antialiasing)

        self.series = []
        self.popup = MyPopup(self)

    def appendCandlestickSeries(self, name):
        ls = QCandlestickSeries()
        ls.setName(name)
        ls.setIncreasingColor(QColor(Qt.green))
        ls.setDecreasingColor(QColor(Qt.red))
        self.series.append(ls)
        return ls

    def appendCandlestickSeriesData(self, ls, dtaware, ope, hig, clo, low):
        x = dtaware2epochms(dtaware)
        ls.append(
            QCandlestickSet(float(ope), float(hig), float(clo), float(low), x))
        if self.maxy == None:
            self.maxy = float(hig)
            self.miny = float(low)
            self.maxx = x
            self.minx = x
        if hig > self.maxy:
            self.maxy = float(hig)
        if low < self.miny:
            self.miny = float(low)
        if x > self.maxx:
            self.maxx = x
        if x < self.minx:
            self.minx = x

    def setOHCLDuration(self, ohclduration):
        self.__ohclduration = ohclduration

    def appendScatterSeries(self, name):
        ls = QScatterSeries()
        ls.setName(name)
        self.series.append(ls)
        return ls

    def appendScatterSeriesData(self, ls, x, y):
        self.appendTemporalSeriesData(ls, x, y)

    def setAxisFormat(self, axis, min, max, type, zone=None):
        """
            type=0 #Value
            type=1 # Datetime
            
            if zone=None remains in UTC, zone is a zone object.
        """
        if type == 0:
            if max - min <= Decimal(0.01):
                axis.setLabelFormat("%.4f")
            elif max - min <= Decimal(100):
                axis.setLabelFormat("%.2f")
            else:
                axis.setLabelFormat("%i")
        elif type == 1:
            max = epochms2dtaware(max)  #UTC aware
            min = epochms2dtaware(min)
            if max - min < timedelta(days=1):
                axis.setFormat("hh:mm")
            else:
                axis.setFormat("yyyy-MM-dd")

    def setAllowHideSeries(self, boolean):
        self._allowHideSeries = boolean

    def appendTemporalSeries(self, name):
        ls = QLineSeries()
        ls.setName(name)
        self.series.append(ls)
        return ls

    def appendTemporalSeriesData(self, ls, x, y):
        """
            x is a datetime zone aware
        """
        x = dtaware2epochms(x)
        x = float(x)
        y = float(y)
        ls.append(x, y)

        if self.maxy == None:  #Gives first maxy and miny
            self.maxy = y * 1.01
            self.miny = y * 0.99
            self.maxx = x * 1.01
            self.minx = x * 0.99

        if y > self.maxy:
            self.maxy = y
        if y < self.miny:
            self.miny = y
        if x > self.maxx:
            self.maxx = x
        if x < self.minx:
            self.minx = x

    def mouseMoveEvent(self, event):
        ##Sets the place of the popup in the windows to avoid getout of the screen
        ##frmshow can be a frmShowCasilla or a frmShowFicha
        def placePopUp():
            resultado = QPoint(event.x() + 15, event.y() + 15)
            if event.x() > self.width() - self.popup.width() - 15:
                resultado.setX(event.x() - self.popup.width() - 15)
            if event.y() > self.height() - self.popup.height() - 15:
                resultado.setY(event.y() - self.popup.height() - 15)
            return resultado

        def showCurrentPosition():
            if hasattr(self, "qgstiCurrentX") == False:
                self.qgstiCurrentX = QGraphicsSimpleTextItem(self.chart())
                self.qgstiCurrentY = QGraphicsSimpleTextItem(self.chart())
            self.qgstiCurrentX.setPos(event.pos().x(), maxY - 10)
            self.qgstiCurrentY.setPos(self.chart().size().width() - 47,
                                      event.pos().y())
            self.qgstiCurrentX.setText(str(epochms2dtaware(xVal).date()))
            self.qgstiCurrentY.setText(str(round(yVal, 2)))

        # ---------------------------------------
        QChartView.mouseMoveEvent(self, event)
        xVal = self.chart().mapToValue(event.pos()).x()
        yVal = self.chart().mapToValue(event.pos()).y()

        maxX = self.axisX.max().toMSecsSinceEpoch()
        minX = self.axisX.min().toMSecsSinceEpoch()
        maxY = self.axisY.max()
        minY = self.axisY.min()
        if xVal <= maxX and xVal >= minX and yVal <= maxY and yVal >= minY:
            self.popup.move(self.mapToGlobal(placePopUp()))
            self.popup.refresh(self, xVal, yVal)
            showCurrentPosition()
            self.popup.show()
        else:
            self.popup.hide()

    ## Return the value of the serie in x
    def series_value(self, serie, x):
        for point in serie.pointsVector():
            if point.x() >= x:
                return point.y()

    @pyqtSlot()
    def on_marker_clicked(self):
        marker = QObject.sender(
            self
        )  #Busca el objeto que ha hecho la signal en el slot en el que está conectado, ya que estaban conectados varios objetos a una misma señal
        marker.series().setVisible(not marker.series().isVisible())
        marker.setVisible(True)
        if marker.series().isVisible():
            alpha = 1
        else:
            alpha = 0.5

        lbrush = marker.labelBrush()
        color = lbrush.color()
        color.setAlphaF(alpha)
        lbrush.setColor(color)
        marker.setLabelBrush(lbrush)

        brush = marker.brush()
        color = brush.color()
        color.setAlphaF(alpha)
        brush.setColor(color)
        marker.setBrush(brush)

        pen = marker.pen()
        color = pen.color()
        color.setAlphaF(alpha)
        pen.setColor(color)
        marker.setPen(pen)

    ## Used to display chart. You cannot use it twice. close the view widget and create another one
    def display(self):
        if self.__chart != None:
            del self.__chart
        self.__chart = QChart()
        self.setChart(self.__chart)
        if self._animations == True:
            self.chart().setAnimationOptions(QChart.AllAnimations)
        else:
            self.chart().setAnimationOptions(QChart.NoAnimation)
        self.chart().layout().setContentsMargins(0, 0, 0, 0)
        self._display_set_title()

        self.setAxisFormat(self.axisX, self.minx, self.maxx, 1)
        self.setAxisFormat(self.axisY, self.miny, self.maxy, 0)
        self.chart().addAxis(self.axisY, Qt.AlignLeft)
        self.chart().addAxis(self.axisX, Qt.AlignBottom)

        for s in self.series:
            self.chart().addSeries(s)
            s.attachAxis(self.axisX)
            s.attachAxis(self.axisY)
        self.axisY.setRange(self.miny, self.maxy)

        #Legend positions
        if len(self.chart().legend().markers()) > 6:
            self.chart().legend().setAlignment(Qt.AlignLeft)
        else:
            self.chart().legend().setAlignment(Qt.AlignTop)

        if self._allowHideSeries == True:
            for marker in self.chart().legend().markers():
                try:
                    marker.clicked.disconnect()
                except:
                    pass
                marker.clicked.connect(self.on_marker_clicked)
        self.repaint()

    ## Returns a qmenu to be used in other qmenus
    def qmenu(self, title="Chart options"):
        menu = QMenu(self)
        menu.setTitle(self.tr(title))
        menu.addAction(self.actionSave)
        return menu

    def on_customContextMenuRequested(self, pos):
        self.qmenu().exec_(self.mapToGlobal(pos))
コード例 #6
0
class VCScatterAlone(VCCommons):
    def __init__(self):
        VCCommons.__init__(self)
        self.clear()
        self.popuplock = QMutex()
        self._x_format = "float"
        self._x_decimals = 2
        self._x_title = ""
        self._y_format = "float"
        self._y_decimals = 2
        self._y_title = ""

    ## To clean pie, removes serie and everithing is like create an empty pie
    def clear(self):
        self._chart = QChart()
        self.setChart(self._chart)
        self.setRenderHint(QPainter.Antialiasing)
        self._allowHideSeries = True

        self.axisX = QValueAxis()
        self.maxx = None
        self.minx = None

        self.axisY = QValueAxis()
        self.maxy = None
        self.miny = None

        self.series = []
        self.chart().legend().hide()
        self.popup = MyPopup(self)

    def appendScatterSeries(self, name, list_x, list_y):
        ls = QScatterSeries()
        ls.setName(name)
        self.series.append(ls)
        for i in range(len(list_x)):
            x = float(list_x[i])
            y = float(list_y[i])
            ls.append(x, y)

            if self.maxy == None:  #Gives first maxy and miny
                self.maxy = y * 1.01
                self.miny = y * 0.99
                self.maxx = x * 1.01
                self.minx = x * 0.99

            if y > self.maxy:
                self.maxy = y
            if y < self.miny:
                self.miny = y
            if x > self.maxx:
                self.maxx = x
            if x < self.minx:
                self.minx = x

    def setXFormat(self, stringtype, title="", decimals=2):
        self._x_format = stringtype
        self._x_decimals = decimals
        self._x_title = title

    def _applyXFormat(self):
        #        self.axisX.setTickCount(8)
        self.axisX.setTitleText(self._x_title)
        if self._x_format == "int":
            self.axisX.setLabelFormat("%i")
        elif self._x_format in ["float", "Decimal"]:
            self.axisX.setLabelFormat("%.{}f".format(self._x_decimals))

    def setYFormat(self, stringtype, title="", decimals=2):
        self._y_format = stringtype
        self._y_decimals = decimals
        self._y_title = title

    def _applyYFormat(self):
        self.axisY.setTitleText(self._y_title)
        if self._y_format == "int":
            self.axisY.setLabelFormat("%i")
        elif self._y_format in ["float", "Decimal"]:
            self.axisY.setLabelFormat("%.{}f".format(self._y_decimals))

    def setAllowHideSeries(self, boolean):
        self._allowHideSeries = boolean

    def mouseMoveEvent(self, event):
        ##Sets the place of the popup in the windows to avoid getout of the screen
        ##frmshow can be a frmShowCasilla or a frmShowFicha
        def placePopUp():
            resultado = QPoint(event.x() + 15, event.y() + 15)
            if event.x() > self.width() - self.popup.width() - 15:
                resultado.setX(event.x() - self.popup.width() - 15)
            if event.y() > self.height() - self.popup.height() - 15:
                resultado.setY(event.y() - self.popup.height() - 15)
            return resultado

        # ---------------------------------------
        if self.popuplock.tryLock() == False:
            event.reject()
            return
        QChartView.mouseMoveEvent(self, event)
        xVal = self.chart().mapToValue(event.pos()).x()
        yVal = self.chart().mapToValue(event.pos()).y()

        maxX = self.axisX.max()
        minX = self.axisX.min()
        maxY = self.axisY.max()
        minY = self.axisY.min()
        if xVal <= maxX and xVal >= minX and yVal <= maxY and yVal >= minY:
            self.popup.move(self.mapToGlobal(placePopUp()))
            self.popup.refresh(self, xVal, yVal)
        self.popuplock.unlock()

    @pyqtSlot()
    def on_marker_clicked(self):
        marker = QObject.sender(
            self
        )  #Busca el objeto que ha hecho la signal en el slot en el que está conectado, ya que estaban conectados varios objetos a una misma señal
        marker.series().setVisible(not marker.series().isVisible())
        marker.setVisible(True)
        if marker.series().isVisible():
            alpha = 1
        else:
            alpha = 0.5

        lbrush = marker.labelBrush()
        color = lbrush.color()
        color.setAlphaF(alpha)
        lbrush.setColor(color)
        marker.setLabelBrush(lbrush)

        brush = marker.brush()
        color = brush.color()
        color.setAlphaF(alpha)
        brush.setColor(color)
        marker.setBrush(brush)

        pen = marker.pen()
        color = pen.color()
        color.setAlphaF(alpha)
        pen.setColor(color)
        marker.setPen(pen)

    ## Used to display chart. You cannot use it twice. close the view widget and create another one
    def display(self):
        if self._chart != None:
            del self._chart
        self._chart = QChart()
        self.setChart(self._chart)
        if self._animations == True:
            self.chart().setAnimationOptions(QChart.AllAnimations)
        else:
            self.chart().setAnimationOptions(QChart.NoAnimation)
        self.chart().layout().setContentsMargins(0, 0, 0, 0)
        self._display_set_title()

        self._applyXFormat()
        self._applyYFormat()
        self.chart().addAxis(self.axisY, Qt.AlignLeft)
        self.chart().addAxis(self.axisX, Qt.AlignBottom)

        for s in self.series:
            self.chart().addSeries(s)
            s.attachAxis(self.axisX)
            s.attachAxis(self.axisY)
        self.axisY.setRange(self.miny, self.maxy)

        #Legend positions
        if len(self.chart().legend().markers()) > 6:
            self.chart().legend().setAlignment(Qt.AlignLeft)
        else:
            self.chart().legend().setAlignment(Qt.AlignTop)

        if self._allowHideSeries == True:
            for marker in self.chart().legend().markers():
                try:
                    marker.clicked.disconnect()
                except:
                    pass
                marker.clicked.connect(self.on_marker_clicked)
        self.repaint()

    ## Returns a qmenu to be used in other qmenus
    def qmenu(self, title="Chart options"):
        menu = QMenu(self)
        menu.setTitle(self.tr(title))
        menu.addAction(self.actionCopyToClipboard)
        menu.addSeparator()
        menu.addAction(self.actionSave)
        return menu

    ## If you use VCPieAlone you can add a context menu setting boolean to True
    def setCustomContextMenu(self, boolean):
        self.customContextMenuRequested.connect(
            self.on_customContextMenuRequested)

    def on_customContextMenuRequested(self, pos):
        self.qmenu().exec_(self.mapToGlobal(pos))
コード例 #7
0
class VCTemporalSeriesAlone(VCCommons):
    def __init__(self):
        VCCommons.__init__(self)
        self.clear()
        self.popuplock = QMutex()
        self._x_format = "date"
        self._x_timezone = "UTC"
        self._x_decimals = 0  #Needed in popup
        self._x_tickcount = 8
        self._x_title = ""
        self._y_format = "float"
        self._y_decimals = 2
        self._y_title = ""

    ## To clean pie, removes serie and everithing is like create an empty pie
    def clear(self):
        self._chart = QChart()
        self.setChart(self._chart)
        self.setRenderHint(QPainter.Antialiasing)
        self._allowHideSeries = True

        self.axisX = QDateTimeAxis()
        self.maxx = None
        self.minx = None

        self.axisY = QValueAxis()
        self.maxy = None
        self.miny = None

        self.series = []
        self.chart().legend().hide()
        self.popup = MyPopup(self)

    def appendCandlestickSeries(self, name):
        ls = QCandlestickSeries()
        ls.setName(name)
        ls.setIncreasingColor(QColor(Qt.green))
        ls.setDecreasingColor(QColor(Qt.red))
        self.series.append(ls)
        return ls

    def appendCandlestickSeriesData(self, ls, dtaware, ope, hig, clo, low):
        x = dtaware2epochms(dtaware)
        ls.append(
            QCandlestickSet(float(ope), float(hig), float(clo), float(low), x))
        if self.maxy == None:
            self.maxy = float(hig)
            self.miny = float(low)
            self.maxx = x
            self.minx = x
        if hig > self.maxy:
            self.maxy = float(hig)
        if low < self.miny:
            self.miny = float(low)
        if x > self.maxx:
            self.maxx = x
        if x < self.minx:
            self.minx = x

    ## Used to draw poinnts in a temporal series
    def appendScatterSeries(self, name):
        ls = QScatterSeries()
        ls.setName(name)
        self.series.append(ls)
        return ls

    def appendScatterSeriesData(self, ls, x, y):
        self.appendTemporalSeriesData(ls, x, y)

    ## @param stringtype is one of the types in casts.value2object. Can be auto too to auto select best datetime format
    def setXFormat(self, stringtype, title="", zone_name="UTC", tickcount=8):
        self._x_format = stringtype
        self._x_zone_name = zone_name
        self._x_tickcount = tickcount
        self._x_title = title

    def _applyXFormat(self):
        self.axisX.setTickCount(8)
        self.axisX.setTitleText(self._x_title)
        if self._x_format == "time":
            self.axisX.setFormat("hh:mm")
        else:
            self.axisX.setFormat("yyyy-MM-dd")

    def setYFormat(self, stringtype, title="", decimals=2):
        self._y_format = stringtype
        self._y_decimals = decimals
        self._y_title = title

    def _applyYFormat(self):
        self.axisY.setTitleText(self._y_title)
        if self._y_format == "int":
            self.axisY.setLabelFormat("%i")
        elif self._y_format in ["float", "Decimal"]:
            self.axisY.setLabelFormat("%.{}f".format(self._y_decimals))

    def setAllowHideSeries(self, boolean):
        self._allowHideSeries = boolean

    def appendTemporalSeries(self, name):
        ls = QLineSeries()
        ls.setName(name)
        self.series.append(ls)
        return ls

    def appendTemporalSeriesData(self, ls, x, y):
        """
            x is a datetime zone aware
        """
        x = dtaware2epochms(x)
        y = float(y)
        ls.append(x, y)

        if self.maxy == None:  #Gives first maxy and miny
            self.maxy = y * 1.01
            self.miny = y * 0.99
            self.maxx = x * 1.01
            self.minx = x * 0.99

        if y > self.maxy:
            self.maxy = y
        if y < self.miny:
            self.miny = y
        if x > self.maxx:
            self.maxx = x
        if x < self.minx:
            self.minx = x

    def mouseMoveEvent(self, event):
        ##Sets the place of the popup in the windows to avoid getout of the screen
        ##frmshow can be a frmShowCasilla or a frmShowFicha
        def placePopUp():
            resultado = QPoint(event.x() + 15, event.y() + 15)
            if event.x() > self.width() - self.popup.width() - 15:
                resultado.setX(event.x() - self.popup.width() - 15)
            if event.y() > self.height() - self.popup.height() - 15:
                resultado.setY(event.y() - self.popup.height() - 15)
            return resultado

        # ---------------------------------------

        if self.popuplock.tryLock() == False:
            event.reject()
            return
        QChartView.mouseMoveEvent(self, event)
        xVal = self.chart().mapToValue(event.pos()).x()
        yVal = self.chart().mapToValue(event.pos()).y()

        maxX = self.axisX.max().toMSecsSinceEpoch()
        minX = self.axisX.min().toMSecsSinceEpoch()
        maxY = self.axisY.max()
        minY = self.axisY.min()
        if xVal <= maxX and xVal >= minX and yVal <= maxY and yVal >= minY:
            self.popup.move(self.mapToGlobal(placePopUp()))
            self.popup.refresh(self, xVal, yVal)
        self.popuplock.unlock()

    ## Return the value of the serie in x
    def series_value(self, serie, x):
        if serie.__class__.__name__ == "QLineSeries":
            for point in serie.pointsVector():
                if point.x() >= x:
                    return point.y()
        elif serie.__class__.__name__ == "QCandlestickSeries":
            for qohcl in serie.sets():
                if qohcl.timestamp() >= x:
                    return qohcl.close

    ## Returns values from QSeries objects in an ordereddict d[x]=y, key is a dtaware
    def series_dictionary(self, serie):
        d = OrderedDict()
        if serie.__class__.__name__ == "QLineSeries":
            for point in serie.pointsVector():
                d[epochms2dtaware(point.x())] = point.y()
        elif serie.__class__.__name__ == "QCandlestickSeries":
            for qohcl in serie.sets():
                d[epochms2dtaware(qohcl.timestamp())] = qohcl.close
        return d

    @pyqtSlot()
    def on_marker_clicked(self):
        marker = QObject.sender(
            self
        )  #Busca el objeto que ha hecho la signal en el slot en el que está conectado, ya que estaban conectados varios objetos a una misma señal
        marker.series().setVisible(not marker.series().isVisible())
        marker.setVisible(True)
        if marker.series().isVisible():
            alpha = 1
        else:
            alpha = 0.5

        lbrush = marker.labelBrush()
        color = lbrush.color()
        color.setAlphaF(alpha)
        lbrush.setColor(color)
        marker.setLabelBrush(lbrush)

        brush = marker.brush()
        color = brush.color()
        color.setAlphaF(alpha)
        brush.setColor(color)
        marker.setBrush(brush)

        pen = marker.pen()
        color = pen.color()
        color.setAlphaF(alpha)
        pen.setColor(color)
        marker.setPen(pen)

    ## Used to display chart. You cannot use it twice. close the view widget and create another one
    def display(self):
        if self._chart != None:
            del self._chart
        self._chart = QChart()
        self.setChart(self._chart)
        if self._animations == True:
            self.chart().setAnimationOptions(QChart.AllAnimations)
        else:
            self.chart().setAnimationOptions(QChart.NoAnimation)
        self.chart().layout().setContentsMargins(0, 0, 0, 0)
        self._display_set_title()

        self._applyXFormat()
        self._applyYFormat()
        self.chart().addAxis(self.axisY, Qt.AlignLeft)
        self.chart().addAxis(self.axisX, Qt.AlignBottom)

        for s in self.series:
            self.chart().addSeries(s)
            s.attachAxis(self.axisX)
            s.attachAxis(self.axisY)
        self.axisY.setRange(self.miny, self.maxy)

        #Legend positions
        if len(self.chart().legend().markers()) > 6:
            self.chart().legend().setAlignment(Qt.AlignLeft)
        else:
            self.chart().legend().setAlignment(Qt.AlignTop)

        if self._allowHideSeries == True:
            for marker in self.chart().legend().markers():
                try:
                    marker.clicked.disconnect()
                except:
                    pass
                marker.clicked.connect(self.on_marker_clicked)
        self.repaint()

    ## Returns a qmenu to be used in other qmenus
    def qmenu(self, title="Chart options"):
        menu = QMenu(self)
        menu.setTitle(self.tr(title))
        menu.addAction(self.actionCopyToClipboard)
        menu.addSeparator()
        menu.addAction(self.actionSave)
        return menu

    ## If you use VCPieAlone you can add a context menu setting boolean to True
    def setCustomContextMenu(self, boolean):
        self.customContextMenuRequested.connect(
            self.on_customContextMenuRequested)

    def on_customContextMenuRequested(self, pos):
        self.qmenu().exec_(self.mapToGlobal(pos))