Matplotlib: getting a figure to show without plt.show()

Peter Otten __peter__ at web.de
Wed Oct 22 06:38:02 EDT 2014


Peter Pearson wrote:

> I'm using Matplotlib to present a "control" window with clickable
> buttons, and to plot things in another window when you click buttons,
> in the style of the code below.  I'm ashamed of the stinky way I
> use "first" to call plt.show the first time data are plotted but then
> to call fig.canvas.draw for subsequent data plots.  

> def callback(event):
>     global n, first
>     fig = plt.figure(2)
>     fig.clear()
>     plt.plot([0,1],[0,n])
>     n += 1  # (Pretending something changes from one plot to the next.)
>     if first:
>         first = False
>         plt.show()
>     else:
>         fig.canvas.draw()

> Can someone tell me the right way?

I don't see what's wrong with doing something different the first time 
around.

> If I call plt.show every time, then after about 40 plots I get
> "RuntimeError: maximum recursion depth exceeded while calling a Python
> object", which makes sense because I'm getting one layer deeper in
> callbacks with every plot (plt.show doesn't return).  But if I call
> fig.canvas.draw every time, the window for the data plot never appears
> on my screen.

If your backend uses tkinter, then the problem may be that plt.show() starts 
a new mainloop. Over here this causes the script to hang on termination. 
Through try-and-error I came up with

import matplotlib.pyplot as plt
from matplotlib.widgets import Button

def callback(event):
    global n, fig2

    if fig2 is None:
        fig2 = plt.figure(2)

    fig2.clear()
    fig2.gca().plot([0, .5, 1], [0, 1/n, 1])
    fig2.show()

    n += 1 

n = 1
fig2 = None

plt.figure(1)

quit_button = Button(plt.axes([.1, .3, .4, .2]), "Quit")
quit_button.on_clicked(lambda x: plt.close("all"))

plot_button = Button(plt.axes([.1, .1, .4, .2]), "Plot")
plot_button.on_clicked(callback)

plt.show()

If you don't mind that the second window shows up immediately you can modify 
that to

import matplotlib.pyplot as plt
from matplotlib.widgets import Button

def callback(event):
    global n

    fig2.clear()
    fig2.gca().plot([0, .5, 1], [0, 1/n, 1])
    fig2.show()

    n += 1 

n = 1

plt.figure(1)

quit_button = Button(plt.axes([.1, .3, .4, .2]), "Quit")
quit_button.on_clicked(lambda x: plt.close("all"))

plot_button = Button(plt.axes([.1, .1, .4, .2]), "Plot")
plot_button.on_clicked(callback)

fig2 = plt.figure(2)

plt.show()

and thus avoid the special case. 

As I'm not an expert for matplotlib you might also post your question on the 
matplotlib mailing list.




More information about the Python-list mailing list