SapFireMC
SapFireMC

Reputation: 43

Tkinter: Irregular spacing for widgets in frames using grid columns

I am attempting to create a relatively simple survey like form in Tkinter, and I'm relatively new to the GUI framework. I'm having real issues trying to figure out why there are so many inconsistencies, especially when working with grid placement+frames+multiple widgets in same row. Especially this specific example. I'm tying together all my questions into a single frame, and it seems to work out... sort of half. Though the rows seem to cooperate nicely, the columns are where the whole thing gets erupted.

qframe1 = Frame(question, bg='black')
qframe1.grid(row=1, padx = 20, sticky = W)

q1l = Label(qframe1, text = 'Question 1: How often do you eat at Mcdonalds?', font = ('Calibri', 14), bg = 'azure')
q1l.grid(columnspan = 4, pady = 5, sticky = W)
q1 = StringVar()
q1.set('None')
q1r1 = Radiobutton(qframe1, text = 'Everyday!', font = ('Calibri', 12), bg = 'azure', variable = q1, value = 'Always')
q1r1.grid(row=1, column = 0, pady = 5, sticky = W)
q1r2 = Radiobutton(qframe1, text = 'Sometimes', font = ('Calibri', 12), bg = 'azure', variable = q1, value = 'Sometimes')
q1r2.grid(row=1, column = 1, pady = 5, sticky = W)
q1r3 = Radiobutton(qframe1, text = 'Not Frequently', font = ('Calibri', 12), bg = 'azure', variable = q1, value = 'Infrequent')
q1r3.grid(row=1, column = 2, pady = 5, sticky = W)
q1r4 = Radiobutton(qframe1, text = 'Never', font = ('Calibri', 12), bg = 'azure', variable = q1, value = 'Never')
q1r4.grid(row=1, column = 3, pady = 5, sticky = W)

This is the bare code for the section that's messing up.
enter image description here

Also, I have made sure that it's not the length of each radio button that is causing the issue. When I change the text of the radio buttons, they still get placed in the same irregular positions.

Here's the code for another section of the trivia.

q2l = Label(qframe1, text = 'Question 2: What meal do you normally order?', font = ('Calibri', 14), bg = 'azure')
q2l.grid(row=2, columnspan = 4, pady = 5, sticky = W)
q2 = StringVar()
q2.set('None')
q2r1 = Radiobutton(qframe1, text = 'Fries', font = ('Calibri', 12), bg = 'azure', variable = q2, value = 'Fries')
q2r1.grid(row=3, column = 0, pady = 5, sticky = W)
q2r2 = Radiobutton(qframe1, text = 'Hamburgers', font = ('Calibri', 12), bg = 'azure', variable = q2, value = 'Hamburgers')
q2r2.grid(row=3, column = 1, pady = 5, sticky = W)
q2r3 = Radiobutton(qframe1, text = 'Chicken Nuggets', font = ('Calibri', 12), bg = 'azure', variable = q2, value = 'Chicken Nuggets')
q2r3.grid(row=3, column = 2, pady = 5, sticky = W)
q2r4 = Radiobutton(qframe1, text = 'Coffee', font = ('Calibri', 12), bg = 'azure', variable = q2, value = 'Coffee')
q2r4.grid(row=3, column = 3, pady = 5, sticky = W)

This again causes an irregular spacing. But this time, the spacing is completely different from the radio buttons in question 1. And rinse and repeat with every new question set of radio buttons.

enter image description here

There are no issues with the buttons on the right side. Perhaps it's because they're aligned in rows and not columns which are causing the spacing issue.

bframe = Frame(question, bg='black')
bframe.grid(row=1, padx = 20, sticky = E)

audioq1 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q1audio)
audioq1.grid(ipadx = 5, pady = 20)
audioq2 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q2audio)
audioq2.grid(row = 1, ipadx = 5, pady = 20)
audioq3 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q3audio)
audioq3.grid(row = 2, ipadx = 5, pady = 20)
audioq4 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q4audio)
audioq4.grid(row = 3, ipadx = 5, pady = 20)
audioq5 = Button(bframe, text = ' Listen to Audio', font = ('Calibri', 14), bg = 'brown1', fg = 'azure', image = sound, relief = SUNKEN, compound = LEFT, command = q5audio)
audioq5.grid(row = 4, ipadx = 5, pady = 20)

enter image description here

Any help would be greatly appreciated!

Upvotes: 4

Views: 479

Answers (1)

Reblochon Masque
Reblochon Masque

Reputation: 36732

If, as mentioned in the comments, "weight isn't necessarily the problem", the placement of the radiobuttons can be realized using pack instead of grid.
This gives something like this (on a mac):

enter image description here

If you want a more evenly placed buttons to fill the available width, you can achieve this with grid:

enter image description here

I also rewrote a portion of the code to make it easier to add questions to the form. Each question is now in its own frame, allowing for more flexibility.

import tkinter as tk


class QFrame(tk.Frame):
    id = 1
    
    def __init__(self, master, question):
        self.master = master
        super().__init__(self.master)
        self.id = QFrame.id
        QFrame.id += 1
        
        self.q = tk.StringVar()
        self.q.set('None')
        
        self.question, self.choices = question
                    
        self.q_label = tk.Label(self, text=f'Question {self.id}: {self.question}')
        self.q_label.pack(expand=True, anchor=tk.W)
        
        self.choose = []
        for idx, choice in enumerate(self.choices):
            txt, value = choice
            qr = tk.Radiobutton(self, text=txt, variable=self.q, value=value)
            self.choose.append(qr)
            qr.pack(side=tk.LEFT)
            

class App(tk.Tk):
    def __init__(self, questions):
        self.questions = questions
        super().__init__()
        
        for question in questions:
            self.qframe = QFrame(self, question)
            self.qframe.pack(fill=tk.X)
        
            
q1 = ['How often do you eat at Mcdonalds?', 
     (('Everyday!', 'Always'), 
      ('Sometimes', 'Sometimes'), 
      ('Not Frequently', 'Infrequent'),
      ('Never', 'Never'))]
              
q2 = ['What meal do you normally order?', 
     (('Fries!', 'Fries'), 
      ('Hamburgers', 'Hamburgers'), 
      ('Chicken Nuggets', 'Chicken Nuggets'),
      ('Coffee', 'Coffee'))]

q3 = ['how large is your usual party?', 
     (('alone!', 'alone'), 
      ('two', 'two'), 
      ('less than 5', 'less than 5'),
      ('5 or more', '5 or more'))]


questions = [q1, q2, q3]
app = App(questions)
app.mainloop()

The code for grid geometry manager:

class QFrame(tk.Frame):
    id = 1
    
    def __init__(self, master, question):
        self.master = master
        super().__init__(self.master)
        self.id = QFrame.id
        QFrame.id += 1
        
        self.q = tk.StringVar()
        self.q.set('None')
        
        self.question, self.choices = question
        
        self.grid_rowconfigure(0, weight=1)
        for idx in range(4):
            self.grid_columnconfigure(idx, weight=1)
                    
        self.q_label = tk.Label(self, text=f'Question {self.id}: {self.question}')
        self.q_label.grid(row=0, column=0, columnspan=4, sticky="w")
        
        self.choose = []
        for idx, choice in enumerate(self.choices):
            txt, value = choice
            qr = tk.Radiobutton(self, text=txt, variable=self.q, value=value)
            self.choose.append(qr)
            qr.grid(row=1, column=idx, columnspan=1, sticky="ew")

Upvotes: 1

Related Questions