Search code examples
pythonmatplotlibcanvastkinterfigure

FigureCanvasTkAgg resizes if its figure is refreshed


I am working on a matplotlib figure embedded in a tkinter gui in Python.

First a FigureCanvasTkAgg is created, which includes a previously created object, which contains a matplotlib figure and then it is drawn. This part works perfectly fine. Afterwards I want to refresh the canvas / its content based on an user action. If the method to refresh the canvas is called, the figure object is refreshed and the canvas is redrawn. This works as well, the figure is updated, but for some strange reason, the canvas resizes, so it shrinks to about one quarter of its original size. If I print the size of the canvas, I can see that its size changed.

I have tried to resize the canvas back to its original size after the refreshment, without success.

I would be thankful for any input. I have added a shortend version of my code.

    #canvas object which is displayed on the gui
    class Canvas:
        def __init__(self, parent):
            #the map_figure object is create
            self.map_figure = map_figure()
            #the matplotlib figure is extracted from the map_figure
            self.figure = self.map_figure.get_figure()
            #the canvas is created using the figure and the parent
            self.canvas = FigureCanvasTkAgg(self.figure, master=parent)
            #I tried both, to manually set the canvas size to the window dimensions (which are
            #described by w and h and using the .pack() parameters, both are working fine
            self.canvas.get_tk_widget().config(width=w,height=h)
            #self.canvas.get_tk_widget().pack(fill='both', expand=True)
            self.canvas.get_tk_widget().pack()
            #canvas is drawn
            self.canvas.draw()
            #its size is printed
            print(self.get_size())

       def refresh(self, parent, point):
            #the map_figure of the canvas is refresh
            self.map_figure.refresh(data)
            #the matplotlib figure is extracted  again
            self.canvas.figure = self.map_figure.get_figure()
            #canvas is redrawn
            self.canvas.draw()
            #the canvas size is now different for some reason even after calling 
            #self.canvas.get_tk_widget().config(width=w,height=h) before this again
            print(self.canvas.get_width_height())

    #the map_figure class if relevant
    class map_figure:
        def __init__(self, data):
            self.figure = self.create_figure(data)

        def get_figure(self):
            return self.figure

        def create_figure(self, data): 
            #creating a matplotlib figure, closing if there was one before
            plt.close(fig=None)
            fig = plt.figure()
            #creating a figure using the data here
            return fig

        #refreshing the figure using new data
        def refresh(self, data):
            self.figure = self.create_figure(data)

Here are also two picture to visualize my problem:

Before State by initialization / before user action

After State after user action


Solution

  • clf()

    Instead of closing the figure each time you refresh it, you could clear it:

    def create_figure(self, date): 
        #creating a matplotlib figure, closing if there was one before
        try:
            self.figure.clf()
            fig = self.figure
        except:
            fig = plt.figure()
        #creating a figure using the data here
        ...