How do I let my Tkinter-Canvas have a fixed width/height ratio when resizing the window

I have the following chessboard: Chessboard

And I want the canvas which holds the chessboard to always remain a square, no matter how I resize the Window, any help is appreciated!


Solution 1:

This can get complicated if you have multiple items in a window and want to constrain a single widget. The correct answer will depend on what else is going on in the window and what sort of resize behavior you've defined.

A simple method is to make sure that the canvas is in a region that will not resize. For example:

import tkinter as tk

root = tk.Tk()

root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(1, weight=1)

canvas = tk.Canvas(root, width=400, height=400, bg="bisque")
canvas.grid(row=0, column=1, sticky="nsew")

root.mainloop()

You can also constrain the window as a whole to a specific aspect ratio with wm_aspect. This lets you resize the window, but the window as a whole will retain a specific aspect ratio.

For example, to force the root window to be a square you can do this:

root = tk.Tk()
root.wm_aspect(1, 1, 1, 1)

From the tcl/tk man pages (and translated to python syntax):

window.wm_aspect(?minNumer minDenom maxNumer maxDenom?) - If minNumer, minDenom, maxNumer, and maxDenom are all specified, then they will be passed to the window manager and the window manager should use them to enforce a range of acceptable aspect ratios for window. The aspect ratio of window (width/length) will be constrained to lie between minNumer/minDenom and maxNumer/maxDenom. If minNumer etc. are all specified as empty strings, then any existing aspect ratio restrictions are removed. If minNumer etc. are specified, then the command returns an empty string. Otherwise, it returns a tuple containing four elements, which are the current values of minNumer, minDenom, maxNumer, and maxDenom (if no aspect restrictions are in effect, then an empty string is returned).