pythonmatplotlibtkinter

Tkinter: resizing figure, old one visible below


I have a tkinter application with a canvas containing a figure. I am trying to change the height of the figure.

I created an entry field ("figure_height_entry") to get the figure height from the user. Upon pressing "Enter", the figure is resized using the function update_figure_size().

The resizing works but if making the figure smaller (let's say by entering "500"), the old figure, larger, is still visible below.

I tried to add fig.clear() in the update_figure_size() function, it gives a blank square with the old figure still visible below.

How can I remove/hide the old figure when resizing it?

MWE:

from tkinter import Label, Tk, IntVar, Entry
import matplotlib.pyplot as plt
import matplotlib
matplotlib.use("TkAgg")
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

def plot_data():
    ax.clear()
    ax.plot([20,22,24,26,28],[5,10,8,3,6])
    canvas.draw_idle()
    
def update_figure_size():
    fig.set_size_inches(700*px, figure_height.get()*px)
    plot_data()
    
# MAIN CODE

root = Tk()

px = 1/plt.rcParams['figure.dpi']# with default figure.dpi = 100
figure_height = IntVar(value=600)
figure_height_entry = Entry(master=root,textvariable=figure_height)
        
fig = plt.Figure(figsize=(700*px, figure_height.get()*px))
ax = fig.add_subplot(111)
canvas = FigureCanvasTkAgg(fig, master = root)
canvas.get_tk_widget().grid(column=0, row=0)

label = Label(root, text="Figure height:")
label.grid(column=1,row=0)

figure_height_entry.bind('<Return>', lambda e: update_figure_size())
figure_height_entry.grid(column=2,row=0)  

plot_data()

root.mainloop()

Solution

  • The configure method of FigureCanvasTkAgg.get_tk_widget offers you the possibility to reconfigure the resources of a widget.

    You probably will need to change the calculation of the size. As you see I added a factor of 100 assuming the size given is in pixel.

    The documentation states, that height and width can be given in different coordinates, but the coordinates part of the documentation is still empty.

    See my changes to your update_figure_size() function.

    from tkinter import Label, Tk, IntVar, Entry
    import matplotlib.pyplot as plt
    import matplotlib
    
    matplotlib.use("TkAgg")
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
    
    
    def plot_data():
        ax.clear()
        ax.plot([20, 22, 24, 26, 28], [5, 10, 8, 3, 6])
        canvas.draw_idle()
    
    
    def update_figure_size():
        canvas.get_tk_widget().configure(width=700 * px * 100, height=figure_height.get() * px * 100)
    
    
    # MAIN CODE
    
    root = Tk()
    
    px = 1 / plt.rcParams['figure.dpi']  # with default figure.dpi = 100
    figure_height = IntVar(value=600)
    figure_height_entry = Entry(master=root, textvariable=figure_height)
    
    fig = plt.Figure(figsize=(700 * px, figure_height.get() * px))
    ax = fig.add_subplot(111)
    canvas = FigureCanvasTkAgg(fig, master=root)
    canvas.get_tk_widget().grid(column=0, row=0)
    
    label = Label(root, text="Figure height:")
    label.grid(column=1, row=0)
    
    figure_height_entry.bind('<Return>', lambda e: update_figure_size())
    figure_height_entry.grid(column=2, row=0)
    
    plot_data()
    
    root.mainloop()
    

    EDIT:

    As I see, you're calculating your figure size in inch. So maybe you want to use this instead:

    canvas.get_tk_widget().configure(width=str(700 * px) + 'i', height=str(figure_height.get() * px) + 'i')
    

    However, take care that you're now setting the canvas size and not the figure size anymore, which slightly changes the size. Consider setting the canvas size also in the beginning.