pythontkinterlabelheightframes

Tkinter frames height and width not matching the full size of the main window


import tkinter


class MainBox:
    def __init__(self):
        # Main windows specifications
        self.root = tkinter.Tk()
        self.root.title(' Utility Box')
        self.root.geometry('700x450')
        self.root.resizable(False, False)
        self.root.configure(bg='red')
        self.root.iconbitmap(r'D:\2xProjects\Python\UtilityBox\resources\appicon.ico')
        self.window_already_open = False

    # Operations frame (search, sort, delete, rename etc)
    self.operations_frame = tkinter.Frame(self.root, width=700, height=350, bg='#293556')
    self.operations_frame.grid(row=0, sticky='ew')

    # Log frame
    # Will log the results of the operations (either success or failure)
    # Ex search: found the file/ files in the specified path
    self.log_frame = tkinter.Frame(self.root, width=700, height=100, bg='#2E4583')
    self.log_frame.grid(row=1, sticky='ew')

    # Search window where user must fill the details required for the operation to start
    def search_details():
        if not self.window_already_open:
            self.window_already_open = True
            search_window = tkinter.Toplevel()
            search_window.title('Search options')
            search_window.geometry('250x160')
            search_window.resizable(False, False)
            search_window.configure(bg='#293556')

            file_path = tkinter.Label(search_window, width=35, wraplength=150)
            file_path.grid(row=0, column=0, sticky='nw', padx=(15, 5), pady=(15, 0))

            # Search based on the file name (ex: name or name.extension)
            file_name = tkinter.Label(search_window, width=35, wraplength=150)
            file_name.grid(row=1, column=0, sticky='nw', padx=(15, 5), pady=(15, 0))

            # Search files with the associated extension (ex: all .txt files)
            extension = tkinter.Label(search_window, width=35, wraplength=150)
            extension.grid(row=2, column=0, sticky='nw', padx=(15, 5), pady=(15, 0))

            start_searching = tkinter.Button(search_window, text='Start searching', bg='#294F63', fg='white')
            start_searching.grid(row=4, column=0, sticky='nw', padx=15, pady=(15, 0))

            def on_window_close():
                self.window_already_open = False
                search_window.destroy()

            search_window.protocol("WM_DELETE_WINDOW", on_window_close)

    # Search functionality (button and description of the functionality)
    search_option = tkinter.Button(self.operations_frame, text='Search', bg='#294F63', fg='white',
                                   command=search_details)
    search_option.grid(row=0, column=0, sticky='nw', padx=15, pady=(15, 0))

    search_description = tkinter.Label(self.operations_frame,
                                       text='Search description')
    search_description.grid(row=0, column=0, sticky='nw', padx=70, pady=(18, 0))

    # Sort functionality (button and description of the functionality)
    sort_option = tkinter.Button(self.operations_frame, text='Sort', bg='#294F63', fg='white')
    sort_option.grid(row=1, column=0, sticky='nw', padx=15, pady=(5, 0))

    sort_description = tkinter.Label(self.operations_frame,
                                     text='Sort description')
    sort_description.grid(row=1, column=0, sticky='nw', padx=55, pady=(7, 0))

    # Delete functionality (button and description of the functionality)
    delete_option = tkinter.Button(self.operations_frame, text='Delete', bg='#294F63', fg='white')
    delete_option.grid(row=2, column=0, sticky='nw', padx=15, pady=(5, 0))

    delete_description = tkinter.Label(self.operations_frame,
                                       text='Delete description')
    delete_description.grid(row=2, column=0, sticky='nw', padx=105, pady=(7, 0))

    # Rename functionality (button and description of the functionality)
    rename_option = tkinter.Button(self.operations_frame, text='Rename', bg='#294F63', fg='white')
    rename_option.grid(row=3, column=0, sticky='nw', padx=15, pady=(5, 0))

    rename_description = tkinter.Label(self.operations_frame,
                                       text='Rename description')
    rename_description.grid(row=3, column=0, sticky='nw', padx=105, pady=(7, 0))

    # Duplication functionality (button and description of the functionality)
    duplication_option = tkinter.Button(self.operations_frame, text='Duplication', bg='#294F63', fg='white')
    duplication_option.grid(row=4, column=0, sticky='nw', padx=15, pady=(5, 0))

    duplication_description = tkinter.Label(self.operations_frame,
                                            text='Duplication description')
    duplication_description.grid(row=4, column=0, sticky='nw', padx=105, pady=(7, 0))

    # Permissions functionality (button and description of the functionality)
    permissions_option = tkinter.Button(self.operations_frame, text='Permissions', bg='#294F63', fg='white')
    permissions_option.grid(row=5, column=0, sticky='nw', padx=15, pady=(5, 0))

    permissions_description = tkinter.Label(self.operations_frame,
                                            text='Permissions description')
    permissions_description.grid(row=5, column=0, sticky='nw', padx=105, pady=(7, 0))

    # Compare functionality (button and description of the functionality)
    compare_option = tkinter.Button(self.operations_frame, text='Compare', bg='#294F63', fg='white')
    compare_option.grid(row=6, column=0, sticky='nw', padx=15, pady=(5, 0))

    compare_description = tkinter.Label(self.operations_frame,
                                        text='Compare description')
    compare_description.grid(row=6, column=0, sticky='nw', padx=105, pady=(7, 0))

    # Preview functionality (button and description of the functionality)
    preview_option = tkinter.Button(self.operations_frame, text='Preview', bg='#294F63', fg='white')
    preview_option.grid(row=7, column=0, sticky='nw', padx=15, pady=(5, 0))

    preview_description = tkinter.Label(self.operations_frame,
                                        text='Preview description')
    preview_description.grid(row=7, column=0, sticky='nw', padx=105, pady=(7, 0))

    # Compression/ decompression functionality (button and description of the functionality)
    compression_decompression_option = tkinter.Button(self.operations_frame, text='Compression/ Decompression',
                                                      bg='#294F63', fg='white')
    compression_decompression_option.grid(row=8, column=0, sticky='nw', padx=15, pady=(5, 0))

    compression_decompression_description = tkinter.Label(self.operations_frame,
                                                          text='Compression/ decompression description')
    compression_decompression_description.grid(row=8, column=0, sticky='nw', padx=205, pady=(7, 0))

    # Window running loop
    self.root.mainloop()


if __name__ == '__main__':
    MainBox()

Hello!

Main window problem

Search window problem

I don't know how to fix the main window frames. I don't know if only the log frame is problematic or just there are multiple problems in multiple frames.

Operations frame (350) + log frame (100) = 450 - the full height of the root frame. Why the dimensions are acting different than what I expected?

Also, I don't understand the span of the labels in the search window and why I can't enter anything when the window is active (I can't type anything in them).

Thank you in advance!

I've read the documentation but I can't figure it out. I tried to modify the height mostly since in my logic that should be the issue, but with no success.


Solution

    1. Math 350 + 100 will work, if your frames are both empty. But when you put other widgets to the operations frame (using grid or pack methods), its height will become not 350, but just enough to fit all widgets in it (you can see, that its height finishes just after the compression_decompression_description label). Read more about this there. So, if you want to make frames size constant, you can use grid_propagate method. So add it after you've created the frame(s):

      self.operations_frame = tkinter.Frame(self.root, width=700,
                                            height=350, bg='#293556')
      self.operations_frame.grid_propagate(False)
      self.operations_frame.grid(row=0, sticky='ew')
      

      maybe do the same thing for other frame, if you will create child widgets in it as well.

    2. Labels width is measured not in pixels, but in "characters" or text units, which one unit is usually equal to the width of the zero symbol (0). so labels width of 35 could fit approximately 35 zeros.

    3. Am l right that you are trying to enter something in labels? They have no such functionality. Use Entry or Text widgets instead please.

    What could also be improved:

    I. Use inheritance, in your code you can make your class from a Tk(), root class, like class MainBox(tkinter.Tk). Makes code clearer and easier to read/understand.

    II. Probably instead of doing 350+100, you could use rowconfigure with weight parameter to 1 for example. This will make frame occupy all available space. It will reduce the need of using such math. So add this after root.configure for example, like this:

    self.root.resizable(False, False)
    self.root.configure(bg='red')
    self.root.rowconfigure(0, weight=1)
    

    And change sticky of the operation frame to "ewns" so like self.operations_frame.grid(row=0, sticky='ewns'). By using this you don't need to use grid_propagate and also you can leave the frame without specifying width and height parameters, so self.operations_frame = tkinter.Frame(self.root, bg='#293556')

    III. For the search window, I would also remove line search_window.geometry('250x160'). In my opinion it is better, if the window will match the widgets in it, so by changing them window will be changing as well. This is optional.

    IV. I don't really like how you grid "option"s and "description"s widgets. I think it is better to create some extra frames. It seems that you are trying to make description frames from "Delete" to "preview" starts in the same horizontal position. So you can create a frame for them, and just put your descriptions in column 1. For the rest widgets (search, sort and comp/decomp) you can create a separate frames for each Button+Label, and then similar things. Again, this all can help to reduce math or guessing the numbers for padx.