как установить интервал оси в подсвечнике, используя pyqtgraph с pyqt5?

Я использую 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_()

Результат:

свеча_graph_center

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

Обновлять

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

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

Обновлять

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


person shadow dk    schedule 30.04.2018    source источник
comment
Как получить второе изображение?   -  person eyllanesc    schedule 01.05.2018
comment
@eyllanesc использует тот же код   -  person shadow dk    schedule 01.05.2018
comment
Я получаю первое изображение, а не второе.   -  person eyllanesc    schedule 01.05.2018
comment
@eyllanesc, наконец, обнаружил, что TextItem не может отображаться правильно, после его удаления все станет нормально   -  person shadow dk    schedule 01.05.2018
comment
Но я все еще не могу установить интервал дат по оси X   -  person shadow dk    schedule 01.05.2018


Ответы (1)


Вы должны преобразовать в строку соответствующего формата, используя 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]

Or:

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]

Or:

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]

введите здесь описание изображения

person eyllanesc    schedule 01.05.2018
comment
Яп, но данные точно показать не могут. Первая дата и время: 2018-01-04 00:00:00, 2018-01-05 00:00:00, .... Кажется, значения в tickStrings неверны. - person shadow dk; 01.05.2018
comment
@shadowdk Это из-за того, что они занимают место, pyqtgraph обрабатывает, отображается ли оно, используя размер в качестве ссылки. Что ж, я поищу способ сделать их постоянными. - person eyllanesc; 01.05.2018