Neal Mc Beal
Neal Mc Beal

Reputation: 245

Tkinter: Too much space between label and button frame

I'm pretty new to Tkinter and I build a little window with different widgets.

My Code looks like this:

import tkinter as tk
from tkinter import ttk


class Application(tk.Frame):

    def __init__(self, master):
        super().__init__(master)
        self.master = master
        self.master.geometry("800x600")
        self.master.title("Tkinter Sandbox")
        self.master.grid_rowconfigure(0, weight=1)
        self.master.grid_columnconfigure(1, weight=1)

       self._create_left_frame()
       self._create_button_bar()
       self._create_label_frame()

    def _create_left_frame(self):
       frame = tk.Frame(self.master, bg="red")

       tree_view = ttk.Treeview(frame)
       tree_view.column("#0", stretch=tk.NO)
       tree_view.heading("#0", text="Treeview")
       tree_view.pack(fill=tk.Y, expand=1)
       frame.grid(row=0, column=0, rowspan=2, sticky=tk.N + tk.S)

    def _create_button_bar(self):
       frame = tk.Frame(self.master, bg="blue")

       button_run_single = tk.Button(frame, text="Button 1")
       button_run_all = tk.Button(frame, text="Button 2")
       button_details = tk.Button(frame, text="Button 3")
       button_run_single.grid(row=0, column=0)
       button_run_all.grid(row=0, column=1, padx=(35, 35))
       button_details.grid(row=0, column=2)
       frame.grid(row=0, column=1, sticky=tk.N)

    def _create_label_frame(self):
       frame = tk.Frame(self.master, bg="blue")

       name_label = tk.Label(frame, text="Label 1")
       performance_label = tk.Label(frame, text="Label 2")
       name_entry = tk.Entry(frame)
       performance_entry = tk.Entry(frame)
       name_label.grid(row=0, column=0)
       name_entry.grid(row=0, column=1)
       performance_label.grid(row=1, column=0)
       performance_entry.grid(row=1, column=1)
       frame.grid(row=1, column=1)


if __name__ == '__main__':
    root = tk.Tk()
    app = Application(root)
    app.mainloop()

Between the three buttons and the label + entry frame is a huge space. I want the button and label + entry frame right under each other, without the huge space but the treeview should also expand vertically over the whole application window.

I think the problem might be my row and column configuration but I don't know how to solve this problem.

Upvotes: 2

Views: 3907

Answers (3)

Bryan Oakley
Bryan Oakley

Reputation: 385940

The way you've structured your code makes it hard to see the problem. As a good general rule of thumb, all calls to grid or pack for widgets within a single parent should be in one place. Otherwise, you create dependencies between functions that are hard to see and understand.

I recommend having each of your helper functions return the frame rather than calling grid on the frame. That way you give control to Application.__init__ for the layout of the main sections of the window.

For example:

left_frame = self._create_left_frame()
button_bar = self._create_button_bar()
label_frame = self._create_label_frame()

left_frame.pack(side="left", fill="y")
button_bar.pack(side="top", fill="x")
label_frame.pack(side="top", fill="both", expand=True)

I used pack here because it requires less code than grid for this type of layout. However, if you choose to switch to grid, or wish to add more widgets to the root window later, you only have to modify this one function rather than modify the grid calls in multiple functions.

Note: this requires that your functions each do return frame to pass the frame back to the __init__ method. You also need to remove frame.grid from each of your helper functions.

With just that simple change you end up with the button bar and label/entry combinations at the top of the section on the right. In the following screenshot I changed the background of the button_bar to green so you can see that it fills the top of the right side of the UI.

screenshot

Upvotes: 2

ronan berridge
ronan berridge

Reputation: 36

I prefer to use the Pack Function since it gives a more open window - its easy to configure. When you use Pack() you can use labels with no text and just spaces to create a spacer, by doing this you won't run into the problem your facing.

Upvotes: 1

Programator2
Programator2

Reputation: 11

You need to change line

self.master.grid_rowconfigure(0, weight=1)

to

self.master.grid_rowconfigure(1, weight=1)

so that the second row takes all the space. Then you need to stick widgets from the label frame to its top by adding sticky parameter to the grid call in _create_label_frame:

frame.grid(row=1, column=1, sticky=tk.N)

Upvotes: 1

Related Questions