def _errorBarsDiamondFilled(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s, painter, clip): """Draw diamond filled region inside error bars.""" if None not in (xmin, xmax, ymin, ymax): if not s.FillBelow.hideerror: path = qt4.QPainterPath() utils.addNumpyPolygonToPath(path, clip, xmin, yplotter, xplotter, ymin, xmax, yplotter) utils.brushExtFillPath(painter, s.FillBelow, path, ignorehide=True) if not s.FillAbove.hideerror: path = qt4.QPainterPath() utils.addNumpyPolygonToPath(path, clip, xmin, yplotter, xplotter, ymax, xmax, yplotter) utils.brushExtFillPath(painter, s.FillAbove, path, ignorehide=True)
def setClip(self, painter, bounds): '''Set clipping for graph.''' p = qt4.QPainterPath() p.addEllipse( qt4.QRectF(qt4.QPointF(bounds[0], bounds[1]), qt4.QPointF(bounds[2], bounds[3]))) painter.setClipPath(p)
def draw(self, parentposn, painthelper, outerbounds=None): '''Update the margins before drawing.''' s = self.settings margins = (s.get('leftMargin').convert(painthelper), s.get('topMargin').convert(painthelper), s.get('rightMargin').convert(painthelper), s.get('bottomMargin').convert(painthelper)) bounds = self.computeBounds(parentposn, painthelper, margins=margins) maxbounds = self.computeBounds(parentposn, painthelper) # controls for adjusting graph margins painter = painthelper.painter(self, bounds) painthelper.setControlGraph(self, [ controlgraph.ControlMarginBox(self, bounds, maxbounds, painthelper) ]) # do no painting if hidden if s.hide: return bounds # set graph rectangle attributes path = qt4.QPainterPath() path.addRect( qt4.QRectF(qt4.QPointF(bounds[0], bounds[1]), qt4.QPointF(bounds[2], bounds[3]))) utils.brushExtFillPath(painter, s.Background, path, stroke=s.Border.makeQPenWHide(painter)) # do normal drawing of children # iterate over children in reverse order for c in reversed(self.children): c.draw(bounds, painthelper, outerbounds=outerbounds) # now need to find axes which aren't children, and draw those again axestodraw = set() childrennames = set() for c in self.children: childrennames.add(c.name) try: for axis in c.getAxesNames(): axestodraw.add(axis) except AttributeError: pass axestodraw = axestodraw - childrennames if axestodraw: # now redraw all these axes if they aren't children of us axeswidgets = self.getAxes(axestodraw) for w in axeswidgets: if w is not None: w.draw(bounds, painthelper, outerbounds=outerbounds) return bounds
def drawShape(self, painter, rect): s = self.settings path = qt4.QPainterPath() if s.rounding == 0: path.addRect(rect) else: path.addRoundedRect(rect, s.rounding, s.rounding) utils.brushExtFillPath(painter, s.Fill, path, stroke=painter.pen())
def areaDrawStacked(self, painter, posns, maxwidth, dsvals, axes, widgetposn, clip): """Draw a stacked area plot""" s = self.settings # get axis which values are plotted along ishorz = s.direction == 'horizontal' vaxis = axes[not ishorz] # compute stacked coordinates stackedvals, stackedcoords = self.calcStackedPoints( dsvals, vaxis, widgetposn) # coordinates of origin zerocoords = vaxis.dataToPlotterCoords(widgetposn, N.zeros(posns.shape)) # draw areas (reverse order, so edges are plotted correctly) for dsnum, coords in izip(xrange(len(stackedcoords) - 1, -1, -1), stackedcoords[::-1]): # add points at end to make polygon p1 = N.hstack([[zerocoords[0]], coords, [zerocoords[-1]]]) p2 = N.hstack([[posns[0]], posns, [posns[-1]]]) # construct polygon on path, clipped poly = qt4.QPolygonF() if ishorz: utils.addNumpyToPolygonF(poly, p1, p2) else: utils.addNumpyToPolygonF(poly, p2, p1) clippoly = qt4.QPolygonF() utils.polygonClip(poly, clip, clippoly) path = qt4.QPainterPath() path.addPolygon(clippoly) path.closeSubpath() # actually draw polygon brush = s.BarFill.get('fills').returnBrushExtended(dsnum) utils.brushExtFillPath(painter, brush, path) # now draw lines poly = qt4.QPolygonF() if ishorz: utils.addNumpyToPolygonF(poly, coords, posns) else: utils.addNumpyToPolygonF(poly, posns, coords) pen = s.BarLine.get('lines').makePen(painter, dsnum) painter.setPen(pen) utils.plotClippedPolyline(painter, clip, poly) # draw error bars barwidth = maxwidth * s.barfill for barval, dsval in izip(stackedvals, dsvals): self.drawErrorBars(painter, posns, barwidth, barval, dsval, axes, widgetposn)
def brushExtFillPolygon(painter, extbrush, cliprect, polygon, ignorehide=False): """Fill a polygon with an extended brush.""" clipped = qt4.QPolygonF() polygonClip(polygon, cliprect, clipped) path = qt4.QPainterPath() path.addPolygon(clipped) brushExtFillPath(painter, extbrush, path, ignorehide=ignorehide)
def __init__(self, parent=None): path = qt4.QPainterPath() path.addRect(-4, -4, 8, 8) path.addRect(-5, -5, 10, 10) path.moveTo(-8, 0) path.lineTo(8, 0) path.moveTo(0, -8) path.lineTo(0, 8) qt4.QGraphicsPathItem.__init__(self, path, parent) self.setBrush(qt4.QBrush(qt4.Qt.black)) self.setFlags(self.flags() | qt4.QGraphicsItem.ItemIsFocusable)
def drawTextItem(self, pt, textitem): """Convert text to a path and draw it. """ # print "text", pt, textitem.text() path = qt4.QPainterPath() path.addText(pt, textitem.font(), textitem.text()) fill = self.emf.CreateSolidBrush(self.pencolor) self.emf.SelectObject(fill) self._createPath(path) self.emf.FillPath() self.emf.SelectObject(self.brush) self.emf.DeleteObject(fill)
def _getBezierLine(self, poly): """Try to draw a bezier line connecting the points.""" npts = qtloops.bezier_fit_cubic_multi(poly, 0.1, len(poly) + 1) i = 0 path = qt4.QPainterPath() lastpt = qt4.QPointF(-999999, -999999) while i < len(npts): if lastpt != npts[i]: path.moveTo(npts[i]) path.cubicTo(npts[i + 1], npts[i + 2], npts[i + 3]) lastpt = npts[i + 3] i += 4 return path
def _drawBezierLine(self, painter, xvals, yvals, posn, xdata, ydata): """Handle bezier lines and fills.""" pts = self._getLinePoints(xvals, yvals, posn, xdata, ydata) if len(pts) < 2: return path = self._getBezierLine(pts) s = self.settings if not s.FillBelow.hide: temppath = qt4.QPainterPath(path) temppath.lineTo(pts[-1].x(), posn[3]) temppath.lineTo(pts[0].x(), posn[3]) utils.brushExtFillPath(painter, s.FillBelow, temppath) if not s.FillAbove.hide: temppath = qt4.QPainterPath(path) temppath.lineTo(pts[-1].x(), posn[1]) temppath.lineTo(pts[0].x(), posn[1]) utils.brushExtFillPath(painter, s.FillAbove, temppath) if not s.PlotLine.hide: painter.strokePath(path, s.PlotLine.makeQPen(painter))
def updateState(self, state): """Examine what has changed in state and call apropriate function.""" ss = state.state() if ss & qt4.QPaintEngine.DirtyPen: self._updatePen(state.pen()) if ss & qt4.QPaintEngine.DirtyBrush: self._updateBrush(state.brush()) if ss & qt4.QPaintEngine.DirtyClipPath: self._updateClipPath(state.clipPath(), state.clipOperation()) if ss & qt4.QPaintEngine.DirtyClipRegion: path = qt4.QPainterPath() path.addRegion(state.clipRegion()) self._updateClipPath(path, state.clipOperation()) if ss & qt4.QPaintEngine.DirtyTransform: self._updateTransform(state.matrix())
def drawGraph(self, painter, bounds, datarange, outerbounds=None): '''Plot graph area and axes.''' s = self.settings xw, yw = bounds[2]-bounds[0], bounds[3]-bounds[1] d60 = 60./180.*math.pi ang = math.atan2(yw, xw/2.) if ang > d60: # taller than wider widthh = xw/2 height = math.tan(d60) * widthh else: # wider than taller height = yw widthh = height / math.tan(d60) # box for equilateral triangle self._box = ( (bounds[2]+bounds[0])/2 - widthh, (bounds[1]+bounds[3])/2 - height/2, (bounds[2]+bounds[0])/2 + widthh, (bounds[1]+bounds[3])/2 + height/2 ) self._width = widthh*2 self._height = height # triangle shaped polygon for graph self._tripoly = p = qt4.QPolygonF() p.append( qt4.QPointF(self._box[0], self._box[3]) ) p.append( qt4.QPointF(self._box[0]+widthh, self._box[1]) ) p.append( qt4.QPointF(self._box[2], self._box[3]) ) path = qt4.QPainterPath() path.addPolygon(p) path.closeSubpath() utils.brushExtFillPath(painter, s.Background, path, stroke=s.Border.makeQPenWHide(painter)) # work out origins and size self._size = max(min(s.fracsize, 1.), 0.) # make sure we don't go past the ends of the allowed range # value of origin of left axis at top self._orgleft = min(s.originleft, 1.-self._size) # value of origin of bottom axis at left self._orgbot = min(s.originbottom, 1.-self._size) # origin of right axis at bottom self._orgright = 1. - self._orgleft - (self._orgbot + self._size)
def _errorBarsDiamond(style, xmin, xmax, ymin, ymax, xplotter, yplotter, s, painter, clip): """Draw diamond around error region.""" if None not in (xmin, xmax, ymin, ymax): # expand clip by pen width (urgh) pw = painter.pen().widthF() * 2 clip = qt4.QRectF(qt4.QPointF(clip.left() - pw, clip.top() - pw), qt4.QPointF(clip.right() + pw, clip.bottom() + pw)) path = qt4.QPainterPath() utils.addNumpyPolygonToPath(path, clip, xmin, yplotter, xplotter, ymax, xmax, yplotter, xplotter, ymin) painter.setBrush(qt4.QBrush()) painter.drawPath(path)
def drawFillPts(self, painter, extfill, cliprect, ptsx, ptsy): '''Draw points for plotting a fill.''' pts = qt4.QPolygonF() utils.addNumpyToPolygonF(pts, ptsx, ptsy) filltype = extfill.filltype if filltype == 'center': pts.append(qt4.QPointF(self._xc, self._yc)) utils.brushExtFillPolygon(painter, extfill, cliprect, pts) elif filltype == 'outside': pp = qt4.QPainterPath() pp.moveTo(self._xc, self._yc) pp.arcTo(cliprect, 0, 360) pp.addPolygon(pts) utils.brushExtFillPath(painter, extfill, pp) elif filltype == 'polygon': utils.brushExtFillPolygon(painter, extfill, cliprect, pts)
def updateState(self, state): """Examine what has changed in state and call apropriate function.""" ss = state.state() # state is a list of transform, stroke/fill and clip states statevec = list(self.oldstate) if ss & qt4.QPaintEngine.DirtyTransform: self.matrix = state.matrix() statevec[0] = self.transformState() if ss & qt4.QPaintEngine.DirtyPen: self.pen = state.pen() statevec[1] = self.strokeFillState() if ss & qt4.QPaintEngine.DirtyBrush: self.brush = state.brush() statevec[1] = self.strokeFillState() if ss & qt4.QPaintEngine.DirtyClipPath: self._updateClipPath(state.clipPath(), state.clipOperation()) statevec[2] = self.clipState() if ss & qt4.QPaintEngine.DirtyClipRegion: path = qt4.QPainterPath() path.addRegion(state.clipRegion()) self._updateClipPath(path, state.clipOperation()) statevec[2] = self.clipState() # work out which state differs first pop = 0 for i in xrange(2, -1, -1): if statevec[i] != self.oldstate[i]: pop = i + 1 break # go back up the tree the required number of times for i in xrange(pop): if self.oldstate[i]: self.celement = self.celement.parent # create new elements for changed states for i in xrange(pop - 1, -1, -1): if statevec[i]: self.celement = SVGElement(self.celement, 'g', ' '.join(statevec[i])) self.oldstate = statevec
def plotBars(self, painter, s, dsnum, clip, corners): """Plot a set of boxes.""" # get style brush = s.BarFill.get('fills').returnBrushExtended(dsnum) pen = s.BarLine.get('lines').makePen(painter, dsnum) lw = pen.widthF() * 2 # make clip box bigger to avoid lines showing extclip = qt4.QRectF( qt4.QPointF(clip.left() - lw, clip.top() - lw), qt4.QPointF(clip.right() + lw, clip.bottom() + lw)) # plot bars path = qt4.QPainterPath() utils.addNumpyPolygonToPath(path, extclip, corners[0], corners[1], corners[2], corners[1], corners[2], corners[3], corners[0], corners[3]) utils.brushExtFillPath(painter, brush, path, stroke=pen)
def drawGraph(self, painter, bounds, datarange, outerbounds=None): '''Plot graph area and axes.''' s = self.settings if s.maxradius == 'Auto': self._maxradius = datarange[1] else: self._maxradius = s.maxradius self._xscale = (bounds[2] - bounds[0]) * 0.5 self._yscale = (bounds[3] - bounds[1]) * 0.5 self._xc = 0.5 * (bounds[0] + bounds[2]) self._yc = 0.5 * (bounds[3] + bounds[1]) path = qt4.QPainterPath() path.addEllipse( qt4.QRectF(qt4.QPointF(bounds[0], bounds[1]), qt4.QPointF(bounds[2], bounds[3]))) utils.brushExtFillPath(painter, s.Background, path, stroke=s.Border.makeQPenWHide(painter))
def drawTextItem(self, pt, textitem): """Convert text to a path and draw it. """ if self.writetextastext: # size f = textitem.font() if f.pixelSize() > 0: size = f.pixelSize() * scale else: size = f.pointSizeF() * scale * dpi / inch_pt attrb = [ 'x="%s"' % fltStr(pt.x() * scale), 'y="%s"' % fltStr(pt.y() * scale), 'textLength="%s"' % fltStr(textitem.width() * scale), ] grp = SVGElement( self.celement, 'g', 'stroke="none" fill="%s" fill-opacity="%.3g" ' 'font-family="%s" font-size="%s"' % (self.pen.color().name(), self.pen.color().alphaF(), escapeXML(textitem.font().family()), size)) text = escapeXML(unicode(textitem.text())) # write as an SVG text element SVGElement(grp, 'text', ' '.join(attrb), text=text.encode('utf-8')) else: # convert to a path path = qt4.QPainterPath() path.addText(pt, textitem.font(), textitem.text()) p = createPath(path) SVGElement( self.celement, 'path', 'd="%s" fill="%s" stroke="none" fill-opacity="%.3g"' % (p, self.pen.color().name(), self.pen.color().alphaF()))
def _fillRegion(self, painter, pxpts, pypts, bounds, belowleft, clip, brush): """Fill the region above/below or left/right of the points. belowleft fills below if the variable is 'x', or left if 'y' otherwise it fills above/right.""" # find starting and ending points for the filled region x1, y1, x2, y2 = bounds pts = qt4.QPolygonF() if self.settings.variable == 'x': if belowleft: pts.append(qt4.QPointF(pxpts[0], y2)) endpt = qt4.QPointF(pxpts[-1], y2) else: pts.append(qt4.QPointF(pxpts[0], y1)) endpt = qt4.QPointF(pxpts[-1], y1) else: if belowleft: pts.append(qt4.QPointF(x1, pypts[0])) endpt = qt4.QPointF(x1, pypts[-1]) else: pts.append(qt4.QPointF(x2, pypts[0])) endpt = qt4.QPointF(x2, pypts[-1]) # add the points between utils.addNumpyToPolygonF(pts, pxpts, pypts) # stick on the ending point pts.append(endpt) # draw the clipped polygon clipped = qt4.QPolygonF() utils.polygonClip(pts, clip, clipped) path = qt4.QPainterPath() path.addPolygon(clipped) utils.brushExtFillPath(painter, brush, path)
def draw(self, posn, phelper, outerbounds=None): """Plot the data on a plotter.""" s = self.settings # exit if hidden if s.hide: return # get points in plotter coordinates xp, yp = self._getPlotterCoords(posn) if xp is None or yp is None: # we can't calculate coordinates return x1, y1, x2, y2 = posn cliprect = qt4.QRectF(qt4.QPointF(x1, y1), qt4.QPointF(x2, y2)) painter = phelper.painter(self, posn, clip=cliprect) pen = s.Line.makeQPenWHide(painter) pw = pen.widthF() * 2 lineclip = qt4.QRectF(qt4.QPointF(x1 - pw, y1 - pw), qt4.QPointF(x2 + pw, y2 + pw)) # this is a hack as we generate temporary fake datasets path = qt4.QPainterPath() for xvals, yvals in document.generateValidDatasetParts( document.Dataset(xp), document.Dataset(yp)): poly = qt4.QPolygonF() utils.addNumpyToPolygonF(poly, xvals.data, yvals.data) clippedpoly = qt4.QPolygonF() utils.polygonClip(poly, lineclip, clippedpoly) path.addPolygon(clippedpoly) path.closeSubpath() utils.brushExtFillPath(painter, s.Fill, path, stroke=pen)
def plotBox(self, painter, axes, boxposn, posn, width, clip, stats): """Draw box for dataset.""" if not N.isfinite(stats.median): # skip bad datapoints return s = self.settings horz = (s.direction == 'horizontal') # convert quartiles, top and bottom whiskers to plotter medplt, botplt, topplt, botwhisplt, topwhisplt = tuple( axes[not horz].dataToPlotterCoords( posn, N.array([ stats.median, stats.botquart, stats.topquart, stats.botwhisker, stats.topwhisker ]))) # draw whisker top to bottom p = s.Whisker.makeQPenWHide(painter) p.setCapStyle(qt4.Qt.FlatCap) painter.setPen(p) swapline(painter, boxposn, topwhisplt, boxposn, botwhisplt, horz) # draw ends of whiskers endsize = width / 2 swapline(painter, boxposn - endsize / 2, topwhisplt, boxposn + endsize / 2, topwhisplt, horz) swapline(painter, boxposn - endsize / 2, botwhisplt, boxposn + endsize / 2, botwhisplt, horz) # draw box fill boxpath = qt4.QPainterPath() boxpath.addRect( swapbox(painter, boxposn - width / 2, botplt, boxposn + width / 2, topplt, horz)) utils.brushExtFillPath(painter, s.Fill, boxpath) # draw line across box p = s.Whisker.makeQPenWHide(painter) p.setCapStyle(qt4.Qt.FlatCap) painter.setPen(p) swapline(painter, boxposn - width / 2, medplt, boxposn + width / 2, medplt, horz) # draw box painter.strokePath(boxpath, s.Border.makeQPenWHide(painter)) # draw outliers painter.setPen(s.MarkersLine.makeQPenWHide(painter)) painter.setBrush(s.MarkersFill.makeQBrushWHide()) markersize = s.get('markerSize').convert(painter) if stats.outliers.shape[0] != 0: pltvals = axes[not horz].dataToPlotterCoords(posn, stats.outliers) otherpos = N.zeros(pltvals.shape) + boxposn if horz: x, y = pltvals, otherpos else: x, y = otherpos, pltvals utils.plotMarkers(painter, x, y, s.outliersmarker, markersize, clip=clip) # draw mean meanplt = axes[not horz].dataToPlotterCoords(posn, N.array([stats.mean]))[0] if horz: x, y = meanplt, boxposn else: x, y = boxposn, meanplt utils.plotMarker(painter, x, y, s.meanmarker, markersize)
def drawShape(self, painter, rect): s = self.settings path = qt4.QPainterPath() path.addEllipse(rect) utils.brushExtFillPath(painter, s.Fill, path, stroke=painter.pen())
def setClip(self, painter, bounds): '''Set clipping for graph.''' p = qt4.QPainterPath() p.addPolygon( self._tripoly ) painter.setClipPath(p)
def draw(self, parentposn, phelper, outerbounds = None): """Plot the key on a plotter.""" s = self.settings if s.hide: return painter = phelper.painter(self, parentposn) font = s.get('Text').makeQFont(painter) painter.setFont(font) height = utils.FontMetrics(font, painter.device()).height() margin = s.marginSize * height showtext = not s.Text.hide # maximum width of text required maxwidth = 1 # total number of layout lines required totallines = 0 # reserve space for the title titlewidth, titleheight = 0, 0 if s.title != '': titlefont = qt4.QFont(font) titlefont.setPointSize(max(font.pointSize() * 1.2, font.pointSize() + 2)) titlewidth, titleheight = utils.Renderer(painter, titlefont, 0, 0, s.title).getDimensions() titleheight += 0.5*margin maxwidth = titlewidth entries = [] # iterate over children and find widgets which are suitable for c in self.parent.children: try: num = c.getNumberKeys() except AttributeError: continue if not c.settings.hide: # add an entry for each key entry for each widget for i in xrange(num): lines = 1 if showtext: w, h = utils.Renderer(painter, font, 0, 0, c.getKeyText(i)).getDimensions() maxwidth = max(maxwidth, w) lines = max(1, math.ceil(float(h)/float(height))) totallines += lines entries.append( (c, i, lines) ) # layout the box layout, (numrows, numcols) = self._layout(entries, totallines) # total size of box symbolwidth = s.get('keyLength').convert(painter) totalwidth = ( (maxwidth + height + symbolwidth)*numcols + height*(numcols-1) ) totalheight = numrows * height + titleheight if not s.Border.hide: totalwidth += 2*margin totalheight += margin # work out horizontal position h = s.horzPosn if h == 'left': x = parentposn[0] + height elif h == 'right': x = parentposn[2] - height - totalwidth elif h == 'centre': x = ( parentposn[0] + 0.5*(parentposn[2] - parentposn[0] - totalwidth) ) elif h == 'manual': x = parentposn[0] + (parentposn[2]-parentposn[0])*s.horzManual # work out vertical position v = s.vertPosn if v == 'top': y = parentposn[1] + height elif v == 'bottom': y = parentposn[3] - totalheight - height elif v == 'centre': y = ( parentposn[1] + 0.5*(parentposn[3] - parentposn[1] - totalheight) ) elif v == 'manual': y = ( parentposn[3] - (parentposn[3]-parentposn[1])*s.vertManual - totalheight ) # for controlgraph boxposn = (x, y) boxdims = (totalwidth, totalheight) # draw surrounding box boxpath = qt4.QPainterPath() boxpath.addRect(qt4.QRectF(x, y, totalwidth, totalheight)) if not s.Background.hide: utils.brushExtFillPath(painter, s.Background, boxpath) if not s.Border.hide: painter.strokePath(boxpath, s.get('Border').makeQPen(painter) ) x += margin y += margin*0.5 # center and draw the title if s.title: xpos = x + 0.5*(totalwidth - (0 if s.Border.hide else 2*margin) - titlewidth) utils.Renderer(painter, titlefont, xpos, y, s.title, alignvert=1).render() y += titleheight textpen = s.get('Text').makeQPen() # plot dataset entries for (plotter, num, xp, yp, lines) in layout: xpos = x + xp*(maxwidth+2*height+symbolwidth) ypos = y + yp*height # plot key symbol painter.save() keyoffset = 0 if s.keyAlign == 'centre': keyoffset = (lines-1)*height/2.0 elif s.keyAlign == 'bottom': keyoffset = (lines-1)*height plotter.drawKeySymbol(num, painter, xpos, ypos+keyoffset, symbolwidth, height) painter.restore() # write key text if showtext: painter.setPen(textpen) utils.Renderer(painter, font, xpos + height + symbolwidth, ypos, plotter.getKeyText(num), -1, 1).render() phelper.setControlGraph( self, [ControlKey(self, parentposn, boxposn, boxdims, height)] )
def draw(self, parentposn, phelper, outerbounds=None, useexistingpainter=None): """Plot the axis on the painter. useexistingpainter is a hack so that a colorbar can reuse the drawing code here. If set to a painter, it will use this rather than opening a new one. """ s = self.settings # recompute if document modified if self.docchangeset != self.document.changeset: self._computePlottedRange() posn = widget.Widget.draw(self, parentposn, phelper, outerbounds) self._updatePlotRange(posn) # get ready to draw if useexistingpainter is not None: painter = useexistingpainter else: painter = phelper.painter(self, posn) # make control item for axis phelper.setControlGraph(self, [ controlgraph.ControlAxisLine( self, s.direction, self.coordParr1, self.coordParr2, self.coordPerp, posn) ]) # get tick vals coordticks = self._graphToPlotter(self.majortickscalc) coordminorticks = self._graphToPlotter(self.minortickscalc) # exit if axis is hidden if s.hide: return texttorender = [] # multiplication factor if reflection on the axis is requested sign = 1 if s.direction == 'vertical': sign *= -1 if self.coordReflected: sign *= -1 # plot gridlines if not s.MinorGridLines.hide: self._drawGridLines('MinorGridLines', painter, coordminorticks, parentposn) if not s.GridLines.hide: self._drawGridLines('GridLines', painter, coordticks, parentposn) # plot the line along the axis if not s.Line.hide: self._drawAxisLine(painter) # plot minor ticks if not s.MinorTicks.hide: self._drawMinorTicks(painter, coordminorticks) # keep track of distance from axis self._delta_axis = 0 # plot major ticks if not s.MajorTicks.hide: self._drawMajorTicks(painter, coordticks) # plot tick labels suppresstext = self._suppressText(painter, parentposn, outerbounds) if not s.TickLabels.hide and not suppresstext: self._drawTickLabels(phelper, painter, coordticks, sign, outerbounds, texttorender) # draw an axis label if not s.Label.hide and not suppresstext: self._drawAxisLabel(painter, sign, outerbounds, texttorender) # mirror axis at other side of plot if s.autoMirror: self._autoMirrorDraw(posn, painter, coordticks, coordminorticks) # all the text is drawn at the end so that # we can check it doesn't overlap drawntext = qt4.QPainterPath() for r, pen in texttorender: bounds = r.getBounds() rect = qt4.QRectF(bounds[0], bounds[1], bounds[2]-bounds[0], bounds[3]-bounds[1]) if not drawntext.intersects(rect): painter.setPen(pen) r.render() drawntext.addRect(rect)