How to expand radio buttons across one row and be formatted correctly

Viewed 196

I am trying to set up the frame of my program. So nothing has a function just yet. I am trying to make all of the radio buttons underneath the search label be formatted across the 2 columns neatly, so that it lines up with the 2 columns above. I will insert a photo of my wireframe. I believe it may be because there is not enough room for all of the radio buttons, but I don't know how to format the above rows in the column to do so. Thank youuuu

Here is my code:

#Component 1 - create the rating frame

from tkinter import *
        
class MovieRaterGUI:

    def __init__(self, parent):

        #variable set up
        self.v = StringVar()
        self.v.set(" ")

        #titles
        self.movie_label = Label(text = "Please Rate:", borderwidth = 10)
        self.movie_label.grid(row = 0, column = 0, sticky = W)
        self.current_movie = Label(text = "The Hobbit", borderwidth = 10)
        self.current_movie.grid(row = 0, column = 1, sticky = W)
        self.rating_label = Label(text = "Your rating:", borderwidth = 10)
        self.rating_label.grid(row = 1, column = 0, sticky = W)

        self.search_label = Label(text = "Search for movies with a rating of:", borderwidth = 10)
        self.search_label.grid(row = 8, column = 0, columnspan = 2)

        
        movies = ["No Rating", "Forget it", "2", "3", "4", "Must See"]

        #making radiobuttons
        for i in range(len(movies)):
            options = Radiobutton(variable = self.v, value = i, text = movies[i], borderwidth = 10)
            options.grid(row = i+1, column = 1, sticky = W)

        for i in range(len(movies)):
            options = Radiobutton(variable = self.v, value = i, text = movies[i])
            options.grid(row = 9, column = i, columnspan = 2, sticky = W)
            i+=1
        

        next_btn = Button(parent, text = "Next", borderwidth = 10)
        next_btn.grid(row = 7, column = 1, sticky = W)

        previous_btn = Button(parent, text = "Previous", borderwidth = 10)
        previous_btn.grid(row = 7, column = 0, sticky = W)

        show_btn = Button(parent, text = "Show", borderwidth = 10)
        show_btn.grid(row = 10, column = 0, columnspan = 2)

if __name__ == "__main__":
    root = Tk()
    root.title("Movie Ratings")
    radiobuttons = MovieRaterGUI(root)
    root.mainloop()

Here is the output:

enter image description here

Here is my wireframe of what I would like it to look like:

enter image description here

Also, if anybody knows why there is only a border on the first radio button the first time I show these radio buttons, that would be much appreciated. :)

1 Answers

Don't try to force everything into a single grid. Looking at your drawing, your program has two clear sections: an upper section with eight rows and two columns, and a bottom section with three rows and six columns. So, start by creating a window with two frames, top and bottom (or pick better names...)

top = Frame(root)
bottom = Frame(root)

Since there are only two, and they should fill the window, pack is the simplest choice for adding them to the window:

top.pack(side="top", expand=True)
bottom.pack(side="bottom", expand=True)

Note: I've chosen pack options to keep the sections centered when you resize the window. I don't know if that's what you want or not.

With that, you can organize the widgets in each section independently. You can keep the top part of your code mostly unchanged, though you'll need to pass top as the first parameter when creating the widgets. I also personally find that grouping grid statements together makes the code easier to read, versus adding a call to grid immediately after creating each widget.

self.movie_label = Label(top, text = "Please Rate:", borderwidth = 10)
self.current_movie = Label(top, text = "The Hobbit", borderwidth = 10)
self.rating_label = Label(top, text = "Your rating:", borderwidth = 10)

self.movie_label.grid(row = 0, column = 0, sticky = W)
self.current_movie.grid(row = 0, column = 1, sticky = W)
self.rating_label.grid(row = 1, column = 0, sticky = W)

for i in range(len(movies)):
    options = Radiobutton(top, variable = self.v, value = i, text = movies[i], borderwidth = 10)
    options.grid(row = i+1, column = 1, sticky = W)

next_btn = Button(top, text = "Next", borderwidth = 10)
previous_btn = Button(top, text = "Previous", borderwidth = 10)

next_btn.grid(row = 7, column = 1, sticky = W)
previous_btn.grid(row = 7, column = 0, sticky = W)

Then, you can do the bottom using grid, but this grid is independent of the grid in the top section.

self.search_label = Label(bottom, text = "Search for movies with a rating of:", borderwidth = 10)
self.search_label.grid(row=0, column=0, columnspan=len(movies))
for i in range(len(movies)):
    options = Radiobutton(bottom, variable = self.v, value = i, text = movies[i])
    options.grid(row = 1, column = i, sticky = W)

show_btn = Button(bottom, text = "Show", borderwidth = 10)
show_btn.grid(row = 3, column = 0, columnspan = len(movies))

There's still some work to be done, since the window may not behave the way you want when you resize it. I'll leave that as an exercise for you since it's not clear what you want to have happen. Regardless, you can set the weights, minimum sizes, padding, etc separately for the top and bottom sections.

screenshot

Related