I am trying to embed a pyplot Figure object in a tkinter GUI and then later on change its size by calling the set_size_inches()
method.
A miniumum (not) working example is provided below. Interestingly, the debug-prints of the Figure and Canvas sizes indicate, that resizing acutally worked. However, the visible size in the GUI stays the same. I hence believe the issue lies somewhere in updating the respective widgets and/or GUI after resizing, but I could not find any solution to change the display of the Figure to its new size.
import tkinter as tk
from tkinter import Frame
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class Gui(tk.Tk):
def __init__(self):
# initialize tkinter
super().__init__()
# enable fullscreen mode
self.state('zoomed')
# create frame
graph_frame = Frame(self)
# create graph
fig = Figure(figsize=(2, 4), frameon=False, tight_layout=True)
ax = fig.add_subplot(111)
canvas = FigureCanvasTkAgg(fig, master=graph_frame)
# place frame
graph_frame.grid(row=8, column=1, columnspan=8)
graph_frame.columnconfigure(0, weight=1)
graph_frame.columnconfigure(1, weight=1)
graph_frame.columnconfigure(2, weight=1)
graph_frame.rowconfigure(0, weight=1)
graph_frame.rowconfigure(1, weight=1)
graph_frame.rowconfigure(2, weight=2)
# place canvas in grid
canvas_widget = canvas.get_tk_widget()
canvas_widget.grid(row=0, column=0, sticky=tk.NSEW)
canvas_widget.update_idletasks()
# enabling this makes it two graphs:
# canvas_widget.update()
# before info
print('Before resize in inches:')
print(fig.get_size_inches())
print(canvas.get_width_height())
# resize graph
fig.set_size_inches(1, 1)
# after info
print('After resize in inches:')
print(fig.get_size_inches())
print(canvas.get_width_height())
# tried any combination and sequence of these, but none work:
canvas.draw()
canvas.get_tk_widget().update()
canvas.draw_idle()
canvas.flush_events()
graph_frame.update()
self.update()
if __name__ == '__main__':
# run GUI
gui = Gui()
gui.mainloop()
Results:
Without the additional canvas_widget.update()
call:
With the additional canvas_widget.update()
call:
I tried updating and flushing each and every possible widget and root in existance, but none worked.
Happy for any hint about what I am doing wrong or how I am misusing stuff :-)
You can change the canvas size according to the desired figsize:
fig.set_size_inches(1, 1, forward = True)
canvas.get_tk_widget().configure(width=fig.get_figwidth()*100, height=fig.get_figheight()*100)
Here the whole code. I implemented a BUtton for testing and put the resizing into a function which is called by the button:
import tkinter as tk
from tkinter import Frame
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
class Gui(tk.Tk):
def __init__(self):
# initialize tkinter
super().__init__()
# enable fullscreen mode
# create frame
self.graph_frame = Frame(self)
self.graph_frame.grid(row=0, column=0)
# create graph
fig = Figure(figsize=(2, 4), frameon=False, tight_layout=True)
ax = fig.add_subplot(111)
canvas = FigureCanvasTkAgg(fig, master=self.graph_frame)
# place frame
# place canvas in grid
canvas_widget = canvas.get_tk_widget()
canvas_widget.grid(row=0, column=0, sticky=tk.NSEW)
canvas_widget.update_idletasks()
# enabling this makes it two graphs:
# canvas_widget.update()
# before info
print('Before resize in inches:')
print(fig.get_size_inches())
print(canvas.get_width_height())
# resize graph
print(fig.get_figwidth(), fig.get_figheight())
btn = tk.Button(self, text='Test', command=lambda : self.resize(fig, canvas))
btn.grid(row = 1, column= 0)
# tried any combination and sequence of these, but none work:
def resize(self, fig, canvas):
fig.set_size_inches(1, 1, forward = True)
canvas.get_tk_widget().configure(width=fig.get_figwidth()*100, height=fig.get_figheight()*100)
# after info
print('After resize in inches:')
print(fig.get_size_inches())
print(canvas.get_width_height())
canvas.co
canvas.draw()
canvas.get_tk_widget().update()
canvas.draw_idle()
canvas.flush_events()
self.graph_frame.update()
self.update()
if __name__ == '__main__':
# run GUI
gui = Gui()
gui.mainloop()