4

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!

SapFireMC
  • 43
  • 5
  • 1
    Are you expecting your `Radiobutton` to occupy the same amount of space, regardless of the length of text? If so you should look into [weight](https://stackoverflow.com/questions/45847313/what-does-weight-do-in-tkinter). – Henry Yik Nov 06 '20 at 08:58
  • 1
    `qframe1` is not defined in your first code block. After changing `qframe = Frame(root)` to `qframe1 = Frame(root)`, the output is not what you show. The radiobuttons are packed together without gap. – acw1668 Nov 06 '20 at 09:01
  • Hi acw1668! Sorry this was completely my bad, I actually have the regular qframe on top of this other frame that I accidentally copied into my post instead of the actual initialization of qframe1. I have what you said, and it produces the output that I have in my post. Edit: I have now edited the post with the fixed code – SapFireMC Nov 06 '20 at 09:41
  • Also in response to Henry Yik, weight isn't necessarily the problem here. I've attempted at it before to see if I could distribute space evenly here by defining each column in the cell, but that doesn't seem to solve the irregular spacing that is happening with the radio buttons. – SapFireMC Nov 06 '20 at 09:46
  • 1
    I still don't get what you show using the updated first code block. All the radiobuttons are packed together. Better show code related to `question` variable. – acw1668 Nov 06 '20 at 10:06

1 Answers1

1

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")
Reblochon Masque
  • 35,405
  • 10
  • 55
  • 80