Python Forum
[Tkinter] Frames layout adding widgets
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Tkinter] Frames layout adding widgets
#1
Hi, i have been struggling with this for days looking at tutorial but just can't get it, i am creating an applications, my thought is to create app, then create frames for each section then add widgets to each section, i think i have the top section done but am trying to add 2 listboxes side by side, different widths on the left of the meetings_frame then i will be adding widgets to the right results_frame , but am stuck, any help please.

from tkinter import *

app = Tk()
app.title("Race Results")
app.geometry("800x400")
app.resizable(width=False, height=False)
app.configure(bg="black")

#create frames
selection_frame = Frame(app, bg="black", width=800, height=50)
meetings_frame = Frame(app, bg="black", width=150, height=350)
mcode_frame = Frame(app, bg="black", width=50, height=350)
results_frame = Frame(app, bg="black", width=600, height=350)
#layout frames
selection_frame.pack(side=TOP)
meetings_frame.pack(side=LEFT)
mcode_frame.pack(side=LEFT)
results_frame.pack(side=RIGHT)


#create selection widget
venue_numberlabel = Label(selection_frame, bg="black", fg="white",  text="Race No", font=("bold", 10), width=7)
venue_numberbox = Entry(selection_frame, bg="#403F3F", fg="white", width=4)
venues = Button(selection_frame, text="Result", bg="#403F3F", fg="white", width=8, command="")
watch = Button(selection_frame, text="Watch Race",  bg="#403F3F", fg="white", width=12, command="")
listen = Button(selection_frame, text="Audio Only", bg="#403F3F", fg="white", width=12, command="")
space = Label(selection_frame, bg="black", width=40)
info = Label(selection_frame, bg="black", fg="white", text="Race Info", font=("bold", 10), width=7)
#layout selection widgets
venue_numberlabel.grid(row=0, column=0, padx=20, pady=5)
venue_numberbox.grid(row=0, column=1, padx=20, pady=5)
venues.grid(row=0, column=2, padx=20, pady=5)
watch.grid(row=0, column=3, padx=20, pady=5)
listen.grid(row=0, column=4, padx=20, pady=5)
space.grid(row=0, column=5)
info.grid(row=1, column=0, padx=20, pady=5)


#create meeting list
meetings = Listbox(meetings_frame, bg="black", fg="white", width=150, height=350)
mcode = Listbox(meetings_frame, bg="black", fg="white", width=50, height=350)
results = Label(meetings, bg="black", fg="white", text="Results", font=("bold", 10), width=600, height=350)
#layout meeting list
meetings.grid(row=0, column=0)
mcode.grid(row=0, column=1)
results.grid(row=0, column=0)
meetings.insert(END, "Meetings")
meetings.itemconfig(END, fg="orange")
mcode.insert(END, "M-Code")
mcode.itemconfig(END, fg="orange")


app.mainloop()
Reply
#2
It would be easier to debug if you changed the colors of the widgets and frames so that you can see what's happening. You have defined the size of the list boxes and labels way to big thinking that you are measuring in pixels when those are measured in character widths. That's why everything seems to disappear on you. See if this helps:
import tkinter as tk

app = tk.Tk()
app.title("Race Results")
app.geometry("800x400")
app.resizable(width=False, height=False)
app.configure(bg="black")

#create frames
selection_frame = tk.Frame(app, bg="blue", width=800, height=50)
meetings_frame = tk.Frame(app, bg="red", width=50, height=330)

#layout frames
selection_frame.pack(side=tk.TOP)
meetings_frame.pack(side=tk.LEFT)

#create selection widget
venue_numberlabel = tk.Label(selection_frame, bg="black", fg="white",  text="Race No", font=("bold", 10), width=7)
venue_numberbox = tk.Entry(selection_frame, bg="#403F3F", fg="white", width=4)
venues = tk.Button(selection_frame, text="Result", bg="#403F3F", fg="white", width=8, command="")
watch = tk.Button(selection_frame, text="Watch Race",  bg="#403F3F", fg="white", width=12, command="")
listen = tk.Button(selection_frame, text="Audio Only", bg="#403F3F", fg="white", width=12, command="")
space = tk.Label(selection_frame, bg="black", width=37)
info = tk.Label(selection_frame, bg="black", fg="white", text="Race Info", font=("bold", 10), width=7)

#layout selection widgets
venue_numberlabel.grid(row=0, column=0, padx=20, pady=5)
venue_numberbox.grid(row=0, column=1, padx=20, pady=5)
venues.grid(row=0, column=2, padx=20, pady=5)
watch.grid(row=0, column=3, padx=20, pady=5)
listen.grid(row=0, column=4, padx=20, pady=5)
space.grid(row=0, column=5)
info.grid(row=1, column=0, padx=20, pady=5)
 

#create meeting list
meetings = tk.Listbox(meetings_frame, bg="green", fg="white", width=10, height=5)
mcode = tk.Listbox(meetings_frame, bg="yellow", fg="white", width=10, height=5)
results = tk.Label(meetings_frame, bg="black", fg="white", text="Results", font=("bold", 10), width=10, height=1)

#layout meeting list
meetings.grid(sticky='nw', row=0, column=0)
mcode.grid(row=0, column=1)
results.grid(row=2, column=0)
meetings.insert(tk.END, "Meetings")
meetings.itemconfig(tk.END, fg="orange")
mcode.insert(tk.END, "M-Code")
mcode.itemconfig(tk.END, fg="orange")
 
app.mainloop ()
Reply
#3
Yes, i can see where i was going wrong, i see you have imported tkinter as tk then assigned that to the other elements, can i ask how this effects them differently to the way i had it?
BashBedlam likes this post
Reply
#4
It's common practice to not use wildcard imports.. That could cause problems down the road if other modules you import have the same name. It may break something.
Better to use import tkinter or import tkinter as tk.
I took a try at your design but, found some thing I don't understand. Mainly you are putting a label in the listbox. Is this where you want it?

import tkinter as tk

class Window:
    def __init__(self, parent):
        self.parent = parent
        self.parent.rowconfigure(0, weight=1)
        self.parent.columnconfigure(0, weight=1)

        # Create container
        container = tk.Frame(self.parent)
        container.grid(column=0, row=0, sticky='news')

        # Create a frame to hold top widgets
        top_frame = tk.Frame(container)
        top_frame['highlightbackground'] = 'lightgray'
        top_frame['highlightcolor'] = 'lightgray'
        top_frame['highlightthickness'] = 1
        top_frame.grid(column=0, row=0, sticky='new', padx=4, pady=4)
        for i in range(2, 5):
            top_frame.columnconfigure(i, weight=3, uniform='buttons')

        # Venue label
        venue_label = tk.Label(top_frame, text='Race No.')
        venue_label.grid(column=0, row=0, sticky='new', padx=8, pady=4)

        # Venue entry label
        venue_entry = tk.Entry(top_frame, width=8)
        venue_entry.grid(column=1, row=0, sticky='new', padx=8, pady=4)

        # Create buttons in a dict. None can be replaced with button commands
        button = {
        'Result': None,
        'Watch Race': None,
        'Audio Only': None
        }

        # Set i = 2 as I want the buttons to start in this column
        i = 2
        for btn, command in button.items():
            btns = tk.Button(top_frame, text=btn)
            btns['command'] = command
            btns.grid(column=i, row=0, sticky='new', padx=8)
            i += 1

        # Create the info label
        info_label = tk.Label(top_frame, text='Race Info.')
        info_label.grid(column=0, row=1, sticky='new', padx=8)

        # reated a container to hold the two listboxes
        frame2 = tk.Frame(container)
        frame2['highlightbackground'] = 'lightgray'
        frame2['highlightcolor'] = 'lightgray'
        frame2['highlightthickness'] = 1
        frame2.grid(column=0, row=1, sticky='new', padx=4, pady=4)
        frame2.columnconfigure(0, weight=3, uniform='listbox')
        frame2.columnconfigure(2, weight=3, uniform='listbox')

        # Note that listbox elements can use commands by binding them to functions
        # Create the first listbox with a scrollbar and inserted data
        scrollbar = tk.Scrollbar(frame2)
        scrollbar.grid(column=1, row=0, sticky='ns')
        meetings = tk.Listbox(frame2, yscrollcommand=scrollbar.set)
        meetings.grid(column=0, row=0, sticky='news', padx=4, pady=4)
        scrollbar.configure(command=meetings.yview)
        for i in range(30):
            meetings.insert(tk.END, f'Meeting {i}')

        # Created the second listbox with a scrollbar
        scrollbar2 = tk.Scrollbar(frame2)
        scrollbar2.grid(column=3, row=0, sticky='ns')
        mcode = tk.Listbox(frame2, yscrollcommand=scrollbar2.set)
        mcode.grid(column=2, row=0, sticky='news', padx=4, pady=4)
        scrollbar2.configure(command=mcode.yview)
        mcode.insert(tk.END, 'M-Code')



def main():
    app = tk.Tk()
    app.geometry('800x400+250+250')
    app.resizable(False, False)
    Window(app)
    app.mainloop()

main()
BashBedlam and Hilal like this post
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#5
I made the adjustments and this is how it should look, colours added to define the areas better.
import tkinter as tk

app = tk.Tk()
app.title("Race Results")
app.geometry("800x400")
app.resizable(width=False, height=False)
app.configure(bg="black")

# create frames
selection_frame = tk.Frame(app, bg="blue", width=800, height=50)
meetings_frame = tk.Frame(app, bg="green", width=200, height=350)
results_frame = tk.Frame(app, bg="red", width=600, height=350)

# layout frames
selection_frame.pack(side=tk.TOP)
meetings_frame.pack(side=tk.LEFT)
results_frame.pack(side=tk.LEFT)

# create selection widget
venue_numberlabel = tk.Label(selection_frame, bg="blue", fg="white", text="Race No", font=("bold", 10), width=7)
venue_numberbox = tk.Entry(selection_frame, bg="#403F3F", fg="white", width=4)
venues = tk.Button(selection_frame, text="Result", bg="#403F3F", fg="white", width=8, command="")
watch = tk.Button(selection_frame, text="Watch Race", bg="#403F3F", fg="white", width=12, command="")
listen = tk.Button(selection_frame, text="Audio Only", bg="#403F3F", fg="white", width=12, command="")
space = tk.Label(selection_frame, bg="blue", width=100)
info = tk.Label(selection_frame, bg="blue", fg="white", text="Race", font=("bold", 10), width=7)

# layout selection widgets
venue_numberlabel.grid(row=0, column=0, padx=20, pady=5)
venue_numberbox.grid(row=0, column=1, padx=20, pady=5)
venues.grid(row=0, column=2, padx=20, pady=5)
watch.grid(row=0, column=3, padx=20, pady=5)
listen.grid(row=0, column=4, padx=20, pady=5)
space.grid(row=0, column=5)
info.grid(row=1, column=0, padx=20, pady=5)

# create meeting list
meetings = tk.Listbox(meetings_frame, bg="lightgrey", fg="white", width=25, height=21)
mcode = tk.Listbox(meetings_frame, bg="grey", fg="white", width=8, height=21)


# layout meeting list
meetings.grid(row=0, column=0)
mcode.grid(row=0, column=1)

##meetings labels
meetings.insert(tk.END, "Meetings")
meetings.itemconfig(tk.END, fg="orange")
mcode.insert(tk.END, "M-Code")
mcode.itemconfig(tk.END, fg="orange")




app.mainloop()
Reply
#6
Using classes to organise the widgets together
import tkinter as tk


class SelectionFrame(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._create_widgets()
        self._layout_widgets()

    def _create_widgets(self):
        self.venue_numberlabel = tk.Label(
            self, bg="blue", fg="white", text="Race No", font=("bold", 10), width=7
        )
        self.venue_numberbox = tk.Entry(self, bg="#403F3F", fg="white", width=4)
        self.venues = tk.Button(
            self, text="Result", bg="#403F3F", fg="white", width=8, command=""
        )
        self.watch = tk.Button(
            self, text="Watch Race", bg="#403F3F", fg="white", width=12, command=""
        )
        self.listen = tk.Button(
            self, text="Audio Only", bg="#403F3F", fg="white", width=12, command=""
        )
        self.space = tk.Label(self, bg="blue", width=100)
        self.info = tk.Label(
            self, bg="blue", fg="white", text="Race", font=("bold", 10), width=7
        )

    def _layout_widgets(self):
        self.venue_numberlabel.grid(row=0, column=0, padx=20, pady=5)
        self.venue_numberbox.grid(row=0, column=1, padx=20, pady=5)
        self.venues.grid(row=0, column=2, padx=20, pady=5)
        self.watch.grid(row=0, column=3, padx=20, pady=5)
        self.listen.grid(row=0, column=4, padx=20, pady=5)
        self.space.grid(row=0, column=5)
        self.info.grid(row=1, column=0, padx=20, pady=5)


class MeetingsFrame(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._create_widgets()
        self._layout_widgets()
        self._insert_meetings_label()
        self._insert_mcode_label()

    def _create_widgets(self):
        self.meetings = tk.Listbox(
            self, bg="lightgrey", fg="white", width=25, height=21
        )
        self.mcode = tk.Listbox(self, bg="grey", fg="white", width=8, height=21)

    def _layout_widgets(self):
        self.meetings.grid(row=0, column=0)
        self.mcode.grid(row=0, column=1)

    def _insert_meetings_label(self):
        self.meetings.insert(tk.END, "Meetings")
        self.meetings.itemconfig(tk.END, fg="orange")

    def _insert_mcode_label(self):
        self.mcode.insert(tk.END, "M-Code")
        self.mcode.itemconfig(tk.END, fg="orange")


class MainFrame(tk.Frame):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.selection_frame = SelectionFrame(self, bg="blue", width=800, height=50)
        self.meetings_frame = MeetingsFrame(self, bg="green", width=200, height=350)
        self.results_frame = tk.Frame(self, bg="red", width=600, height=350)
        self._layout_frames()

    def _layout_frames(self):
        self.selection_frame.pack(side=tk.TOP)
        self.meetings_frame.pack(side=tk.LEFT)
        self.results_frame.pack(side=tk.LEFT)


def main():
    app = tk.Tk()
    app.title("Race Results")
    app.geometry("800x400")
    app.resizable(width=False, height=False)
    app.configure(bg="black")
    main_frame = MainFrame(app)
    main_frame.pack()
    app.mainloop()


if __name__ == "__main__":
    main()
Reply
#7
You seem to have your layout the way you want now. I'm going to post my finished attempt.

import tkinter as tk

class Window:
    def __init__(self, parent):
        self.parent = parent
        self.parent.rowconfigure(0, weight=1)
        self.parent.columnconfigure(0, weight=1)

        # Create container
        container = tk.Frame(self.parent)
        container.grid(column=0, row=0, sticky='news')
        container.grid_columnconfigure(0, weight=3)


        # Create a frame to hold top widgets
        top_frame = tk.Frame(container)
        top_frame['highlightbackground'] = 'lightgray'
        top_frame['highlightcolor'] = 'lightgray'
        top_frame['highlightthickness'] = 1
        top_frame.grid(column=0, row=0, sticky='new', padx=4, pady=4)
        for i in range(2, 7):
            top_frame.columnconfigure(i, weight=2, uniform='buttons')

        # Venue label
        venue_label = tk.Label(top_frame, text='Race No.')
        venue_label.grid(column=0, row=0, sticky='new', padx=8, pady=4)

        # Venue entry label
        venue_entry = tk.Entry(top_frame, width=8)
        venue_entry.grid(column=1, row=0, sticky='new', padx=8, pady=4)

        # Create buttons in a dict. None can be replaced with button commands
        button = {
        'Result': None,
        'Watch Race': None,
        'Audio Only': None
        }

        # Set i = 2 as I want the buttons to start in this column
        i = 2
        for btn, command in button.items():
            btns = tk.Button(top_frame, text=btn)
            btns['command'] = command
            btns.grid(column=i, row=0, sticky='new', padx=8, pady=4)
            i += 1

        # Create a spacer
        spacer = tk.Label(top_frame).grid(column=6, row=0)

        # Create the info label
        info_label = tk.Label(top_frame, text='Race Info.')
        info_label.grid(column=0, row=1, sticky='new', padx=8)

        # Created a container to hold the two listboxes
        frame2 = tk.Frame(container)
        frame2['highlightbackground'] = 'lightgray'
        frame2['highlightcolor'] = 'lightgray'
        frame2['highlightthickness'] = 1
        frame2.grid(column=0, row=1, sticky='new', padx=4, pady=4)
        frame2.grid_columnconfigure(4, weight=3)


        # Note that listbox elements can use commands by binding them to functions
        # Create the first listbox with a scrollbar and inserted data
        scrollbar = tk.Scrollbar(frame2)
        scrollbar.grid(column=1, row=0, sticky='ns')
        meetings = tk.Listbox(frame2, yscrollcommand=scrollbar.set, width=24, height=19)
        meetings.grid(column=0, row=0, sticky='news', padx=4, pady=4)
        scrollbar.configure(command=meetings.yview)
        for i in range(30):
            meetings.insert(tk.END, f'Meeting {i}')

        # Created the second listbox with a scrollbar
        scrollbar2 = tk.Scrollbar(frame2)
        scrollbar2.grid(column=3, row=0, sticky='ns')
        mcode = tk.Listbox(frame2, yscrollcommand=scrollbar2.set, width=10)
        mcode.grid(column=2, row=0, sticky='news', padx=4, pady=4)
        scrollbar2.configure(command=mcode.yview)
        mcode.insert(tk.END, 'M-Code')

        # Create result label
        res_frame = tk.Frame(frame2, bg='#222222')
        res_frame['relief'] = 'groove'
        res_frame.grid(column=4, row=0, sticky='news', padx=4, pady=4)

def main():
    app = tk.Tk()
    app.geometry('800x400+250+250')
    app.resizable(False, False)
    app.title('Race Results')
    Window(app)
    app.mainloop()

main()
I welcome all feedback.
The only dumb question, is one that doesn't get asked.
My Github
How to post code using bbtags


Reply
#8
Thanks all for your help, the way you set out your code tells me i have a lot to learn, cheers.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
Bug [PyQt] Dinamically adding widgets to layout [PySide6] carecavoador 2 1,455 Jun-19-2023, 12:57 PM
Last Post: carecavoador
  pyqt5 layout Nickd12 8 3,488 Jan-18-2021, 09:09 AM
Last Post: Axel_Erfurt
  [PyQt] remove widgets of a layout catlessness 2 11,942 Apr-02-2020, 07:25 PM
Last Post: catlessness
  [Tkinter] Problems with frames layout Gupi 1 2,209 May-27-2019, 09:41 AM
Last Post: Yoriz
  Python GUI layout off between different OS shift838 5 3,702 Jan-02-2019, 02:53 AM
Last Post: shift838
  [Tkinter] grid layout neech 8 17,638 Oct-14-2016, 07:06 PM
Last Post: Larz60+

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020