Hi, I don't have experience writing custom GraphicsObjects, but I think the ViewBox autoscale is doing what it is told to do - it's the way your CandlestickItem is being drawn and/or the way it reports its size to the containing ViewBox when it does its auto ranging.
At the moment, you construct a QPicture on initialisation containing the drawn candlesticks, and then just draw the picture on paint(). The boundingRect is correct, it is the region that the picture will be painted to. But I think you also need to implement a dataBounds() method (http://www.pyqtgraph.org/documentation/graphicsItems/plotdataitem.html#pyqtgraph.PlotDataItem.dataBounds) to report to the ViewBox the range currently in view. This will need to do something like find the intersection of the current self.viewRect() and the data and return the proper range. See maybe the implementations in one of the core GraphicsObjects like PlotCurveItem ( http://www.pyqtgraph.org/documentation/_modules/pyqtgraph/graphicsItems/PlotCurveItem.html <http://www.pyqtgraph.org/documentation/_modules/pyqtgraph/graphicsItems/PlotCurveItem.html#PlotCurveItem> ). Also as an aside, you might be able to stop manual plot scaling and enforce autorange (when you get it working!) with http://www.pyqtgraph.org/documentation/graphicsItems/viewbox.html#pyqtgraph.ViewBox.setMouseEnabled methods. Hope that helps, Patrick On Saturday, 27 April 2019 02:50:47 UTC+9:30, [email protected] wrote: > > It seems like adding in any custom GraphicItems to a plot breaks > autoranging in PyQTgraph, at least it seems to me. > > I added an example below, even when the candlestick item is off to the > side of the plot and is not visible autorange still acts as though it is > onscreen. > > Any ideas of the path to take to get it working ? > > Thanks. > > > > > > > > > > > > import pyqtgraph as pg > from pyqtgraph import QtCore, QtGui > > ## 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('w')) > 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() > > 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()) > > # rescales Y automatically > def setYRange(): > vb.enableAutoRange(x=False, y=True) > vb.setAutoVisible(x=False, y=True) > print('Why me no rescale ? =)') > > data = [ ## fields are (time, open, close, min, max). > (1., 10, 13, 5, 15), > (2., 13, 17, 9, 20), > (3., 17, 14, 11, 23), > (4., 14, 15, 5, 19), > (5., 15, 9, 8, 22), > (6., 9, 15, 8, 16), > (7., 10, 13, 5, 15), > (8., 13, 17, 9, 20), > (9., 17, 14, 11, 23), > (10., 14, 15, 5, 19), > (11., 15, 9, 8, 22), > (12., 9, 15, 8, 16), > (13., 10, 13, 5, 15), > (14., 14, 15, 5, 19), > (15., 15, 9, 8, 22), > (16., 9, 15, 8, 16), > (17., 16, 17, 15, 20), > (18., 17, 21, 20, 23), > (19., 21, 30, 29, 24), > (20., 30, 39, 28, 32), > (21., 39, 37, 35, 40) > > ] > > plt = pg.plot() > item = CandlestickItem(data) > plt.addItem(item) > plt.setWindowTitle('Scaletest') > > # normal lines > import numpy > x_data = numpy.linspace(22, 122, num=100) > y_data = (10*numpy.random.rand(100,1)+30).flatten() > #y_data[5000:] = numpy.sin(x_data[5000:]) > lineitem = pg.PlotDataItem(x_data, y_data) > plt.addItem(lineitem) > > # autoscale aspects > vb = plt.getViewBox() > vb.setAspectLocked(lock=False) > vb.setAutoVisible(y=1.0) > vb.enableAutoRange(axis='y', enable=True) > > # force it to update at rescale > vb.sigXRangeChanged.connect(setYRange) > > ## Start Qt event loop unless running in interactive mode or using pyside. > if __name__ == '__main__': > import sys > if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION' > ): > QtGui.QApplication.instance().exec_() > > > > -- You received this message because you are subscribed to the Google Groups "pyqtgraph" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/pyqtgraph/963edefe-f996-4de7-ab65-b857c5913817%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
