Как установить интервал оси в свече, используя pyqtgraph с pyqt5? - PullRequest
0 голосов
/ 30 апреля 2018

Я использую pyqtgraph, чтобы нарисовать свечу, как показано ниже:

#-------------------
# Create pyqtgraph module 
#------------------- 
def GUI_DRAW_create():
    """
    set default config
    """
    pg.setConfigOption('background', 'w')   #background: white
    pg.setConfigOption('foreground', 'k')   #font: black

class TimeAxisItem(pg.AxisItem):
    def tickStrings(self, values, scale, spacing):
        #values is not my date in timestamp 
        return [datetime.fromtimestamp(value) for value in values]

## Create a subclass of GraphicsObject.
## The only required methods are paint() and boundingRect() 
## (see QGraphicsItem documentation)
class CandlestickItem(pg.GraphicsObject):
    def __init__(self, data):
        pg.GraphicsObject.__init__(self)
        self.data = data  ## data must have fields: time, open, close, min, max
        self.generatePicture()

    def generatePicture(self):
        ## pre-computing a QPicture object allows paint() to run much more quickly, 
        ## rather than re-drawing the shapes every time.
        self.picture = QtGui.QPicture()
        p = QtGui.QPainter(self.picture)
        p.setPen(pg.mkPen('k'))
        w = (self.data[1][0] - self.data[0][0]) / 3.
        for (t, open, close, min, max) in self.data:
            p.drawLine(QtCore.QPointF(t, min), QtCore.QPointF(t, max))
            if open > close:
                p.setBrush(pg.mkBrush('r'))
            else:
                p.setBrush(pg.mkBrush('g'))
            p.drawRect(QtCore.QRectF(t-w, open, w*2, close-open))
        p.end()
        # I try to print out t here, is my date 
    def paint(self, p, *args):
        p.drawPicture(0, 0, self.picture)

    def boundingRect(self):
        ## boundingRect _must_ indicate the entire area that will be drawn on
        ## or else we will get artifacts and possibly crashing.
        ## (in this case, QPicture does all the work of computing the bouning rect for us)
        return QtCore.QRectF(self.picture.boundingRect())


class GUI_DRAW_new(QMainWindow):
    def __init__(self):
        super().__init__()

        GUI_DRAW_create()

        self.setWindowTitle("pyqtgraph example: PlotWidget")

        cw = QWidget()
        self.setCentralWidget(cw)

        main_layout = QHBoxLayout()
        cw.setLayout(main_layout)

        #variable 
        self.signalgraph = None
        self.data = []
        self.vb = None
        self.vLine = None

        # define plot windows
        self.GUI_DRAW_new_graph()
        main_layout.addWidget(self.signalgraph)

        self.signalgraph.setMouseTracking(True)
        self.signalgraph.viewport().installEventFilter(self)

        self.show()

    def eventFilter(self, source, event):
        try:
            if (event.type() == QtCore.QEvent.MouseMove and
                source is self.signalgraph.viewport()):
                pos = event.pos()
                print('mouse move: (%d, %d)' % (pos.x(), pos.y()))
                if self.signalgraph.sceneBoundingRect().contains(pos):
                    mousePoint = self.vb.mapSceneToView(pos)
                    index = int(mousePoint.x())
                    int(index)
                    #if index > 0 and index < len(self.data):
                        #print(self.xdict[index])

                    #    self.label.setHtml("<p style='color:black'>日期:{0}</p>".format(self.data[index]))
                    #    self.label.setPos(mousePoint.x(),mousePoint.y())
                    self.vLine.setPos(mousePoint.x())

            return QtGui.QWidget.eventFilter(self, source, event)
        except Exception as e:
            traceback.print_exc()
            err = sys.exc_info()[1]
            PRINT_DEBUG(0,str(err))

    def GUI_DRAW_new_graph(self):
        try:
            self.signalgraph = pg.PlotWidget(name="Signalgraph", axisItems={'bottom': TimeAxisItem(orientation='bottom')})

            # sample data
            self.data = [  ## fields are (time, open, close, min, max).
                (1514995200.0, 102.610001, 105.349998, 102, 105.370003),
                (1515081600.0, 105.75, 102.709999, 102.410004, 105.849998),
                (1515168000.0, 100.559998, 102.370003, 99.870003, 100.699997),
                (1515254400.0, 98.68, 96.449997, 96.43, 100.129997),
                (1515340800.0, 98.550003, 96.959999, 96.760002, 99.110001),

                (1515427200.0, 102.610001, 105.349998, 102, 105.370003),
                (1515513600.0, 105.75, 102.709999, 102.410004, 105.849998),
                (1515600000.0, 100.559998, 102.370003, 99.870003, 100.699997),
                (1515686400.0, 98.68, 96.449997, 96.43, 100.129997),
                (1515772800.0, 98.550003, 96.959999, 96.760002, 99.110001),
            ]

            #if comment this 2 code, can see the string
            item = CandlestickItem(self.data)
            self.signalgraph.addItem(item)

            #trick
            s_day = datetime.fromtimestamp(self.data[0][0]).strftime("%Y-%m-%d")
            e_day = datetime.fromtimestamp(self.data[len(self.data) - 1][0]).strftime("%Y-%m-%d")
            tr=np.arange(s_day, e_day, dtype='datetime64') # tick labels one day 

            tday0=(tr-tr[0])/(tr[-1]-tr[0])  #Map time to 0.0-1.0 day 2 1.0-2.0 ...
            tday1=tday0+1

            tnorm=np.concatenate([tday0,tday1])
            tr[-1]=tr[0]  # End day=start next day

            ttick=list()    
            for i,t in enumerate(np.concatenate([tr,tr])):
                tstr=np.datetime64(t).astype(datetime)
                ttick.append(  (tnorm[i],  tstr.strftime("%Y-%m-%d")))  

            ax=self.signalgraph.getAxis('bottom')    #This is the trick  
            ax.setTicks([ttick])
            #cross hair in signalgraph
            self.vLine = pg.InfiniteLine(angle=90, movable=False)
            self.signalgraph.addItem(self.vLine, ignoreBounds=True)
            self.vb = self.signalgraph.plotItem.vb

        except Exception as e:
            traceback.print_exc()
            err = sys.exc_info()[1]
            print(0,str(err))


# Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == "__main__":
    app = QtGui.QApplication([])
    gui = GUI_DRAW_new()
    app.exec_()

Результат:

candlestick_graph_center

Я хочу установить интервал оси X, используя дату: [2018-01-04, 2018-01-05, 2018-01-06, ....]. Спасибо за помощь, большое спасибо

Обновление

Я понимаю, почему все данные сжимаются вместе из-за TextItem. Так что, я переписываю код.

Я пытаюсь использовать tickStrings в AxisItem для преобразования значения в строку, когда я печатаю values в tickStrings, это не мое значение данных (дата в метке времени). Почему значения разные? Большое спасибо

Обновление

Если я использую setTicks со свечой, она не может показать строку на графике. Только можно показать строку без подсвечника. Любая идея?

1 Ответ

0 голосов
/ 01 мая 2018

Необходимо преобразовать в строку с соответствующим форматом, используя strftime():

from datetime import datetime

class TimeAxisItem(pg.AxisItem):
    def tickStrings(self, values, scale, spacing):
        #values is not my date in timestamp 
        return [datetime.fromtimestamp(value).strftime("%Y-%m-%d") for value in values]

Или:

from datetime import date

class TimeAxisItem(pg.AxisItem):
    def tickStrings(self, values, scale, spacing):
        #values is not my date in timestamp 
        return [date.fromtimestamp(value) for value in values]

Или:

from datetime import datetime

class TimeAxisItem(pg.AxisItem):
    def tickStrings(self, values, scale, spacing):
        #values is not my date in timestamp 
        return [datetime.fromtimestamp(value).date() for value in values]

enter image description here

...