I'm trying to build a Tkinter form in Python that has three "frames": a narrow frame across the top (for a title), a thin frame down the left (for buttons), and a main frame (to show content). The left frame will have buttons, and the top and main frames will have canvases that can be drawn on. I'd like to use "grid" placement of the Tkinter widgets to simplify layout.
The code below works perfectly if I don't include the canvas in the top panel: the frames, the buttons in the left frame, and the canvas in the main frame are all laid out exactly as I want (and note particularly that the canvas in the main frame sized itself to fit allotted space). (See Figure 1.)
However, when I add a canvas to the top panel (in exactly the same manner as the canvas in the main panel), it doesn't size itself properly. (The width is correct, but the height isn't.) (Figure 2.) How to I make the canvas in the top panel size itself properly (and/or what am I doing wrong)?
Figure 1: Without Canvas in the Top Panel

Figure 2: With Canvas Added To the Top Panel

from tkinter import Tk
tk = Tk()
from tkinter import Frame, Canvas, Button
screenWidth = tk.winfo_screenwidth()
screenHeight = tk.winfo_screenheight()
formWidth = int(screenWidth * 0.8)
formHeight = int(screenHeight * 0.8)
formLeft = (screenWidth - formWidth) // 2
formTop = (screenHeight - formHeight) // 2
tk.geometry(f'{formWidth}x{formHeight}+{formLeft}+{formTop}')
tk.resizable(False, False)
tk.columnconfigure(0, weight=10)
tk.columnconfigure(1, weight=90)
tk.rowconfigure(0, weight=10)
tk.rowconfigure(1, weight=90)
topFrame = Frame(tk, bg="blue", highlightthickness=0)
topFrame.grid(column=0, row=0, columnspan=2, sticky="nwes")
topFrame.columnconfigure(0, weight=1)
topFrame.rowconfigure(0, weight=1)
leftFrame = Frame(tk, bg="green", highlightthickness=0)
leftFrame.grid(column=0, row=1, sticky="nwes")
leftFrame.columnconfigure(0, weight=1)
#leftFrame.rowconfigure(0, weight=1)
mainFrame = Frame(tk, bg="purple", highlightthickness=0)
mainFrame.grid(column=1, row=1, sticky="nwes")
mainFrame.columnconfigure(0, weight=1)
mainFrame.rowconfigure(0, weight=1)
startButton = Button(leftFrame, text="Start")
startButton.grid(column=0, row=0, sticky="ew")
stopButton = Button(leftFrame, text="Stop")
stopButton.grid(column=0, row=1, sticky="ew")
titleCanvas = Canvas(topFrame, bg="indigo", highlightthickness=0)
titleCanvas.grid(column=0, row=0, sticky="nwes")
mainCanvas = Canvas(mainFrame, bg="gray", highlightthickness=0)
mainCanvas.grid(column=0, row=0, sticky="nwes")
tk.update()
# Show that the main canvas has sized itself correctly.
mainCanvas.create_line(0, 0, mainCanvas.winfo_width(), mainCanvas.winfo_height(), width=2, fill="black")
tk.mainloop()