Trouble with the Tkinter Grid manager when a canvas is placed in window

Question:

Python, tkinter, I’m trying to write a program that takes a file and uses its contents to drawl a picture. I can’t get the grid manager to line the widgets up correctly.

I want it to look like the first picture, but it always comes out looking like the second:
https://imgur.com/a/hS7gyqq

In my code, the, "Enter a file name" is in column 0, which should make it all the way to the left. But it only shows up about half way through the window.

Here is the code:

from tkinter import *
from tkinter import filedialog
from tkinter.filedialog import askopenfilename

class LetterCounter():

    def __init__(self):
        #create the window
        window=Tk()
        window.title("Occurance Of Letters")
        window.columnconfigure((1,2,3,4,5,6,7,8,9,10), weight=1)
        window.rowconfigure((1,2,3,4,5,6,7), weight =1)


        window.geometry("700x400")
 
        #create the canvas 
        self.canvas = Canvas(window, width=500, height=300, bg="blue")
        self.canvas.grid(column=0, row=0, padx=100, pady=20)

        BtshowResults = Button(window, text ="Show Results", command = self.showResults).grid(column=6, row = 7)

        BtnBrowse = Button(window, text="Browse", command =self.browseFile).grid(column=4, row =7)
        #create the buttons 
        self.EnterdFile = StringVar()
        Entry(window, textvariable = self.EnterdFile).grid(column=1, row=7)
        Label(window, text="Enter a filename").grid(column=0, row=7)



        window.mainloop()


    #browse file function 
    def browseFile(self):
        filenameForReading = askopenfilename()
        self.EnterdFile.set(filenameForReading)

    #show result function 
    def showResults(self):
        filenameForReading = self.EnterdFile.get()
        letterCount = {} #create empty dictionary 
        infile = open(filenameForReading, "r")
        for line in infile:
            self.processLine(line.lower(), letterCount)

        y = 10
        for ch, count in sorted(letterCount.items()):
            x=500          
            text = f'letter { ch} appears { count}times.'
            self.canvas.create_text(x, y, text=text, fill="black", font=('Helvetica 15 bold'))
            y+=20
            
   

        
    def processLine(self, line, letterCount):
        line = self.replacePunction(line)
        for ch in line: 
            if ch in letterCount:
                letterCount[ch] +=1 
            else: 
                letterCount[ch] = 1



    #replaces punction with blank space

    def replacePunction(self, line):
        for ch in line:
           if not ch.isalpha():
                line = line.replace(ch, "")
        return line

LetterCounter()     

So I have tried adjusting the columns and rows.

I know the problem is tied to the canvas widget, because when I remove it, the lower widgets behave the way I want them to:

https://imgur.com/a/eqcc5rP

How do I make the lower widgets behave in the way I want them to? AKA neatly spaced at the bottom like a normal GUI window?

PS: this is only my 3d stack overflow question, I tried searching the problem, but I apologize in advance if I overlooked the existing answer.

Asked By: Anson.A

||

Answers:

You can set the columnspan option on self.canvas.grid(...) to make the canvas occupies several columns:

# you can adjust the value of columnspan to suit your case
self.canvas.grid(column=0, row=0, padx=100, pady=20, columnspan=8)

Result:

enter image description here

But for flexibility, I would suggest to put the bottom widgets inside a frame.

Answered By: acw1668