You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[Bug]: TkAgg: Subplot layout fails for large initial figure sizes, works when resized smaller (inverted behavior) on Raspberry Pi OS / Matplotlib 3.10.1
#30083
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
Large initial window (1200x800): MRE fails to show all plots correctly.
Resizing MRE window smaller: MRE then shows all plots correctly.
On initial run I should get 4 graphs in a 2 x 2 grid on screen. Except instead I get 1 graph and the others off screen. When I resize the window to a much smaller window the other graphs show up as expected in the much smaller window.
Code for reproduction
importtkinterastkfrommatplotlib.figureimportFigurefrommatplotlib.backends.backend_tkaggimportFigureCanvasTkAggimportmatplotlibimportlogginglogging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")
# --- Test with these values ---TARGET_WIDTH=1200TARGET_HEIGHT=800# --- If above fails, then try these ---# TARGET_WIDTH = 700 # TARGET_HEIGHT = 600# --- ---classMRE_App:
def__init__(self, master):
self.master=mastermaster.title("Matplotlib Layout MRE")
master.geometry(f"{TARGET_WIDTH}x{TARGET_HEIGHT}")
self.fig_dpi=96# Fixed DPI# Option 1: Try with subplots_adjust (NO constrained_layout on Figure)self.fig=Figure(dpi=self.fig_dpi)
logging.info("MRE: Using subplots_adjust approach.")
# Option 2: Try with constrained_layout (comment out subplots_adjust in update_figure_size)# self.fig = Figure(dpi=self.fig_dpi, constrained_layout=True)# self.fig.set_constrained_layout_pads(w_pad=0.02, h_pad=0.02, wspace=0.03, hspace=0.03)# logging.info("MRE: Using constrained_layout approach.")self.ax1=self.fig.add_subplot(221)
self.ax2=self.fig.add_subplot(222)
self.ax3=self.fig.add_subplot(223)
self.ax4=self.fig.add_subplot(224)
fori, axinenumerate([self.ax1, self.ax2, self.ax3, self.ax4]):
ax.plot([0,1], [i, i+1])
ax.set_title(f"Ax {i+1}")
ax.grid(True)
self.canvas=FigureCanvasTkAgg(self.fig, master=master)
self.canvas_widget=self.canvas.get_tk_widget()
self.canvas_widget.pack(side=tk.TOP, fill=tk.BOTH, expand=True)
self.canvas_widget.bind("<Configure>", self.on_resize)
self.master.after(300, self.initial_draw) # Slightly longer delay for MRE toologging.info(f"MRE: Matplotlib version: {matplotlib.__version__}")
try:
logging.info(f"MRE: Tkinter version: {tk.TkVersion}, TclVersion: {tk.TclVersion}")
except:
logging.info("MRE: Could not get Tk/Tcl versions easily.")
definitial_draw(self):
logging.info("MRE: Initial draw triggered")
self.master.update_idletasks()
self.update_figure_size_and_layout() # Combined method# self.canvas.draw_idle() # update_figure_size_and_layout will call itdefon_resize(self, event):
logging.debug(f"MRE: Configure event: w={event.width}, h={event.height}")
ifevent.width<=1orevent.height<=1: returnself.update_figure_size_and_layout()
defupdate_figure_size_and_layout(self):
ifnot (hasattr(self, 'canvas_widget') andself.canvas_widget.winfo_exists()):
returnself.master.update_idletasks() # Ensure Tkinter sizes are accurate before querycanvas_width_px=self.canvas_widget.winfo_width()
canvas_height_px=self.canvas_widget.winfo_height()
logging.debug(f"MRE: Canvas current pixel size: {canvas_width_px}x{canvas_height_px}")
ifcanvas_width_px>1andcanvas_height_px>1:
new_fig_width_inches=canvas_width_px/self.fig.get_dpi()
new_fig_height_inches=canvas_height_px/self.fig.get_dpi()
current_width, current_height=self.fig.get_size_inches()
size_changed=abs(current_width-new_fig_width_inches) >0.01or \
abs(current_height-new_fig_height_inches) >0.01is_initial_draw=nothasattr(self.fig, '_mre_drawn_once')
ifsize_changedoris_initial_draw:
self.fig.set_size_inches(new_fig_width_inches, new_fig_height_inches, forward=True)
logging.info(f"MRE: Figure resized to: {new_fig_width_inches:.2f}x{new_fig_height_inches:.2f} in. Initial: {is_initial_draw}")
ifis_initial_draw:
self.fig._mre_drawn_once=True# --- If testing subplots_adjust (Option 1 for self.fig creation) ---try:
self.fig.subplots_adjust(left=0.10, bottom=0.10, right=0.95, top=0.92, wspace=0.25, hspace=0.25)
logging.debug("MRE: Applied subplots_adjust.")
exceptExceptionase:
logging.error(f"MRE: Error in subplots_adjust: {e}")
# --- If testing constrained_layout (Option 2 for self.fig creation) ---# if not self.fig.get_constrained_layout():# self.fig.set_constrained_layout(True)# logging.info("MRE: Constrained layout re-enabled.")# try:# self.fig.set_constrained_layout_pads(w_pad=0.02, h_pad=0.02, wspace=0.03, hspace=0.03) # Match your app# except Exception as e:# logging.error(f"MRE: Error setting constrained_layout_pads: {e}")self.canvas.draw_idle()
logging.debug("MRE: Canvas draw_idle called.")
else:
logging.debug("MRE: Canvas too small to resize figure.")
if__name__=='__main__':
root=tk.Tk()
app=MRE_App(root)
root.mainloop()
Bug summary
Large initial window (1200x800): MRE fails to show all plots correctly.
Resizing MRE window smaller: MRE then shows all plots correctly.
On initial run I should get 4 graphs in a 2 x 2 grid on screen. Except instead I get 1 graph and the others off screen. When I resize the window to a much smaller window the other graphs show up as expected in the much smaller window.
Code for reproduction
Actual outcome
system details:
Operating System: Debian GNU/Linux 12 (bookworm)
Kernel: Linux 6.12.25+rpt-rpi-v8
Architecture: arm64
Python version: 3.11.x (from your logs)
Matplotlib version: 3.10.1
Tkinter version: 8.6 (from your MRE logs)
Tcl version: 8.6 (from your MRE logs)
Expected outcome
As the window resizes the graphs should resize with the window and display all 4.
Additional information
No response
Operating system
Debian Bookworm
Matplotlib Version
3.10.1
Matplotlib Backend
No response
Python version
3.11.x
Jupyter version
No response
Installation
pip
The text was updated successfully, but these errors were encountered: