I have an App made using Qt4 Designer which inserts a matplotlib figure into a container widget.
The code to generate the figure comes from another module, obspy:
self.st.plot(fig = self.rawDataPlot)
https://docs.obspy.org/packages/autogen/obspy.core.stream.Stream.plot.html
Normally, this would create and show a matplotlib figure for the st
object's data, which is time-series. When the fig
parameter is specified this tells self.st.plot
to plot to an existing matplotlib figure instance.
The code I have to generate the figure and then position it in my GUI widget is:
def addmpl(self, fig, layout, window): # code to add mpl figure to Qt4 widget
self.canvas = FigureCanvas(fig)
layout.addWidget(self.canvas)
self.canvas.draw()
self.toolbar = NavigationToolbar(self.canvas,
window, coordinates=True)
layout.addWidget(self.toolbar)
self.rawDataPlot = plt.figure() # code to create a mpl figure instance
self.st.plot(fig = self.rawDataPlot) # plot time-series data to existing matplotlib figure instance
self.addmpl(self.rawDataPlot, self.mplvl, self.mplwindow) # add mpl figure to Qt4 widget
What I want to do is instantiate a matplot figure (for use by self.st.plot
) but in a way which avoids using plt.figure()
, as I have read that this is bad practice when using object-oriented programming.
If I replace plt.figure()
with Figure()
(from matplotlib.figure.Figure()) I get an error:
AttributeError: 'NoneType' object has no attribute 'draw'
As it stands, the App runs fine if I use plt.figure(), but is there a clean way to avoid using is and is it even necessary for my case?
PS, the code snippets here are taken from a larger source, but I think it gets the point across..
In principle both methods should work.
Whether you set self.rawDataPlot = plt.figure()
or self.rawDataPlot = Figure()
does not make a huge difference, assuming the imports are correct.
So the error is most probably triggered within the self.st.plot()
function. (In general, if you report errors, append the traceback.)
Looking at the source of obspy.core.stream.Stream.plot
there is a keyword argument
:param draw:
If True, the figure canvas is explicitly re-drawn, which ensures that existing figures are fresh. It makes no difference for figures that are not yet visible. Defaults toTrue
.
That means that apparently the plot function tries to draw the canvas, which in the case of providing a Figure()
hasn't yet been set.
A good guess would therfore be to call
self.rawDataPlot = Figure()
self.st.plot(fig = self.rawDataPlot, draw=False)
and see if the problem persists.