Subclassing PyPlot, need some help
Christian K.
ckkart at hoc.net
Wed Aug 1 20:26:50 PDT 2007
Andriy wrote:
> Hi,
>
> I'm working on a subclass of PyPlot (specifically, I'm subclassing
> PlotCanvas from wx.lib.plot). My purpose is to have a plot class that
> can draw multiple subplots into the class canvas. My approach so far
> is this: the derived class constructor takes the number of rows and
> columns, and maintains a list of PlotCanvas instances based on that.
> The class has a Plot method, which takes a PlotGraphics instance and a
> plot index, and draws the graphics to the appropriate plot in the list
> based on the index. The subplots are all equally sized; their size is
> calculated based on the canvas size and number of rows & columns.
> When it will work, it should look something like a pylab plot with
> subplots, though I will index the subplots in the way that a GridSizer
> does (zero-based, left-right, top-to-bottom).
>
> I think that I have built the OnSize event handler properly because I
> can see the SubPlotSize calculating correctly when I resize the parent
> panel. I'm not sure if I have built the OnPaint handler correctly
> because I don't draw to the main canvas yet. Which leads me to my
> questions:
>
> Where do I put the code to draw the subplots together to the canvas?
> Should it be in the Plot method?
> What is the proper DC to use for drawing the subplots to the canvas? I
> am guessing I could use something like:
> dc = wx.BufferedDC(wx.ClientDC(self.canvas), self._Buffer)
> and then pass this dc to PlotCanvas.Draw() ? But it's not quite
> right.. I need multiple dc's from all the plots.
>
> If I do this right, I should be able to save the canvas image to file,
> as well as be able to print it by just delegating these actions to the
> superclass, right?
>
> Here is a (working) skeleton of the subclass:
>
> class FlexPlot(PlotCanvas):
> def __init__(self, parent, rows=1, cols=1, title=''):
> self.parent = parent
> self.rows = rows
> self.cols = cols
> self.title = title
> self.numplots = self.rows * self.cols
> self.plots = []
> for i in xrange(self.numplots):
> self.plots.append(PlotCanvas(parent))
> self.resetDefaults(self.plots[i])
> #now initialize the superclass
> PlotCanvas.__init__(self, parent)
> parent.Bind(wx.EVT_SIZE, self.OnSize)
>
> def OnSize(self, event):
> PlotCanvas.OnSize(self, event)
> for subplot in self.plots:
> PlotCanvas.OnSize(subplot, event)
> buffer = getattr(self, '_Buffer', None)
> if buffer: print 'Buffer size: %s' % (buffer.GetSize(),)
> canvasSize = self.canvas.GetClientSize()
> self.SubPlotSize = (canvasSize[0]/self.rows, canvasSize[1]/self.cols)
> if event is not None:
> event.Skip()
>
> def OnPaint(self, event):
> #invoke the individual OnPaint events
> for subplot in self.plots:
> PlotCanvas.OnPaint(subplot, event)
> event.Skip()
>
> def Plot(self, graphics, index=0, xlim=None, ylim=None,
> grid=False, legend=False):
> """
> Plotting command - wrapper around the
> superclass Draw method to handle multiple subplots.
> graphics: PlotGraphics instance
> index: subplot index (zero-based)
> xlim: tuple of (xmin, xmax) for the X axis
> ylim: tuple of (ymin, ymax) for the Y axis
> grid: turns grid on/off
> legend: turns legend on/off
> """
> subPlot = self.plots[index]
> dc = wx.BufferedDC(wx.ClientDC(self.canvas), self._Buffer)
> self.resetDefaults(subPlot)
> subPlot.Draw(graphics, xAxis=xlim, yAxis=ylim, dc=dc)
> subPlot.SetEnableGrid(grid)
> subPlot.SetEnableLegend(legend)
> subPlot.SetShowScrollbars(False)
To me it looks like you are mixing different approaches. Either subclass
PlotCanvas and modify only the drawing code, i.e. that part that
actually paints the graph, frame, labels, etc. or create a custum class
that contains an arbitrary number of PlotCanvas objects. Note that
PlotCanvas is a wx.Panel, so you might want to put them in a sizer.
Obviously only with the first method you will have a single DC which can
be exported easily.
Currently you're subclassing PlotCanvas and then you put additional
PlotCanvas objects in there. I doubt that this will work.
Christian
More information about the wxpython-users
mailing list