There seems to be an issue with the ipadx and ipady adjustments of the grid method. I tried to add inner padding around a frame such that the elements/subframes contained get "pushed" away from the border resulting in symmetrical whitespace:
import tkinter as tk
import tkinter.font
# Main window
main_window = tk.Tk()
main_window.title('Viewer')
# Main window plotting frame
main_window_plotting_frame = tk.Frame(main_window, borderwidth=2, relief='raised')
main_window_plotting_frame.grid(sticky='nesw')
# General layout settings
default_font = tk.font.nametofont("TkDefaultFont")
default_font.configure(size=11)
title_font = ('TkDefaultFont', 12, 'bold')
small_padding = 5
large_padding = 20
# Preview image frame
preview_frame = tk.Frame(main_window_plotting_frame)
preview_frame.grid(row=0, column=0, ipadx=100, ipady=100)
preview_frame_title = tk.Label(preview_frame, text='Preview', font=title_font)
preview_frame_title.grid(row=0, pady=large_padding)
preview_canvas = tk.Canvas(preview_frame, width=300, height=300, bg='white')
preview_canvas.grid(row=1)
preview_canvas.create_line(0, 300, 300, 0, width=10, fill='light green')
preview_save_button = tk.Button(preview_frame, text='Save as PNG')
preview_save_button.grid(row=2)
# Open main window
main_window.mainloop()
But this results in padding only to the right and the bottom. I've searched for an explanation and only found another user with the same issue, but no solution. I've exaggerated the ipadx and ipady values to make the effect more prominent.
The reason I want inner padding is that I'm trying to solve the annoying issue of "accumulating" whitespace/borders/paddings in complex GUIs with multiple nested frames/subframes. I found that in order to avoid accumulation of padding, one can just eliminate all padding altogether - except for the innermost subframes containing the actual GUI widgets. By doing this, I can use frames in order to group widgets and move them around like modular instrumentation panels, while keeping a constant padding around each such panel. This grouping is not just convenient, but a necessity as it becomes mind-numbingly tedious to edit/maintain complex GUIs without proper grouping into frames and subframes.
UPDATE: An explanation, why the suggested solution of adding another subframe with the same problem doesn't work:
import tkinter as tk
import tkinter.font
# Main window
main_window = tk.Tk()
main_window.title('Viewer')
# Main window plotting frame
main_window_plotting_frame = tk.Frame(main_window, borderwidth=2, relief='raised')
main_window_plotting_frame.grid(sticky='nesw')
# General layout settings
default_font = tk.font.nametofont("TkDefaultFont")
default_font.configure(size=11)
title_font = ('TkDefaultFont', 12, 'bold')
small_padding = 5
large_padding = 20
# Preview image frame
preview_frame = tk.Frame(main_window_plotting_frame)
preview_frame.grid(row=0, column=0, ipadx=100, ipady=100)
preview_preview_frame = tk.Frame(main_window_plotting_frame)
preview_preview_frame.grid(row=0, column=1, ipadx=100, ipady=100)
preview_frame_title = tk.Label(preview_frame, text='Preview', font=title_font)
preview_frame_title.grid(row=0, pady=large_padding)
preview_canvas = tk.Canvas(preview_frame, width=300, height=300, bg='white')
preview_canvas.grid(row=1)
preview_canvas.create_line(0, 300, 300, 0, width=10, fill='light green')
preview_canvas = tk.Canvas(preview_preview_frame, width=300, height=300, bg='white')
preview_canvas.grid(row=1)
preview_canvas.create_line(0, 300, 300, 0, width=10, fill='light green')
preview_save_button = tk.Button(preview_frame, text='Save as PNG')
preview_save_button.grid(row=2)
# Open main window
main_window.mainloop()
By adding a canvas also to the second subframe, you'll see that the problem persists (only now you have asymmetric padding in two instead of one frame).
Okay, I'm now officially declaring this as a BUG inside tkinter! If any tkinter dev reads this, please solve the issue.