Radiobutton choices auto-filled before selection

  • Context: Python 
  • Thread starter Thread starter Eclair_de_XII
  • Start date Start date
  • Tags Tags
    Choices
Join the discussion
Registration is free. Ask a follow-up in this thread, or start your own.
3 replies · 1K views
Eclair_de_XII
Messages
1,085
Reaction score
92
TL;DR
I'm trying to create a frame of Radiobutton widgets, but for some odd reason, the widgets are already filled before the user even selects them. I've tried tinkering with the type of the variable linked to the widgets, but the problem still persists.
Whenever I use a BooleanVar, the side_dish attribute keeps evaluating to False even if I set it to None. So I tried setting it to a StringVar. This time, both the Radiobutton seem to be auto-filled, even though nothing is even selected. If anyone could shed some light on why this happens, I would very much appreciate it. I am not sure if tkinter is still commonly used, but I am intent on sticking to it, either way.

Python:
from tkinter import *

class Restaurant:
    def __init__(self):
        self.side_dish=None
        self.root=Tk()
        self.root.title('Waiter')
        self.mainFrame=Frame(self.root)
        self.mainFrame.grid()

    def endProcess(self,*args):
        self.root.destroy()

    def initializeParams(self,varType):
        if varType == 'str':
            self.side_dish=StringVar()
            self.soupVal='Soup'
            self.saladVal='Salad'
        elif varType == 'bool':
            self.side_dish=BooleanVar()
            self.soupVal=False
            self.saladVal=True

    def chooseSide(self):
        question='Would you like the salad or the soup?'
        #   To create white-space so that title shows
        question+=' '*5
        Label(self.mainFrame,text=question).grid(row=0,columnspan=2)

        d={}
        d['varType']='bool'

        self.initializeParams(**d)

        kw={
            'master':self.mainFrame,\
            'variable':self.side_dish,\
            'command':self.printSelection
            }

        soupButton=Radiobutton(text='Soup',value=self.soupVal,**kw)
        saladButton=Radiobutton(text='Salad',value=self.saladVal,**kw)

        buttonPos={
            'column':0,\
            'sticky':W
            }

        soupButton.grid(row=1,**buttonPos)
        saladButton.grid(row=2,**buttonPos)

        soupButton.focus()

    def printSelection(self,*args):
        chose_salad=self.side_dish.get()
        kw={
            'master':self.mainFrame
            }
        Label(text='User chose salad:',**kw).grid(row=1,column=1)
        Label(text='%s'%chose_salad,**kw).grid(row=2,column=1)

        self.root.bind_all('<Return>',self.endProcess)

    def __call__(self):
        self.root.bind_all('<Escape>',self.endProcess)
        self.chooseSide()

if __name__ == '__main__':
    Restaurant()()
 
Physics news on Phys.org
Boolean is a bad choice for radio buttons - what happens when you want to add another choice? If you want this to be a boolean value then use a checkbox.

Although you initially set side_dish to None you override it in initializeParams to a tk.StringVar. I am not an expert on tkinter but you could try self.side_dish.set('') after line 16.
 
Eclair_de_XII said:
Whenever I use a BooleanVar, the side_dish attribute keeps evaluating to False even if I set it to None.

Of course, because None is not a boolean value in Python; only False and True are. Whenever you hand an object to a BooleanVar, it converts it to a Python boolean value (using the built-in function bool, AFAIK, which evaluates to False if called with None as its argument).

Eclair_de_XII said:
So I tried setting it to a StringVar.

Normally, AFAIK, radio buttons are expected to map to zero-based integer values.
 
PeterDonis said:
zero-based integer values

It baffles me how simple the solution I came up with was, based on this remark alone. Thanks.

[CODE lang="python" highlight="23-26,35"]from tkinter import *

class Restaurant:
def __init__(self):
self.side_dish=None
self.root=Tk()
self.root.title('Waiter')
self.mainFrame=Frame(self.root)
self.mainFrame.grid()

def endProcess(self,*args):
self.root.destroy()

def initializeParams(self,varType):
if varType == 'str':
self.side_dish=StringVar()
self.soupVal='Soup'
self.saladVal='Salad'
elif varType == 'bool':
self.side_dish=BooleanVar()
self.soupVal=False
self.saladVal=True
elif varType == 'int':
self.side_dish=IntVar(value=-1)
self.saladVal=1
self.soupVal=0

def chooseSide(self):
question='Would you like the salad or the soup?'
# To create white-space so that title shows
question+=' '*5
Label(self.mainFrame,text=question).grid(row=0,columnspan=2)

d={}
d['varType']='int'

self.initializeParams(**d)

kw={
'master':self.mainFrame,\
'variable':self.side_dish,\
'command':self.printSelection
}

soupButton=Radiobutton(text='Soup',value=self.soupVal,**kw)
saladButton=Radiobutton(text='Salad',value=self.saladVal,**kw)

buttonPos={
'column':0,\
'sticky':W
}

soupButton.grid(row=1,**buttonPos)
saladButton.grid(row=2,**buttonPos)

soupButton.focus()

def printSelection(self,*args):
chose_salad=self.side_dish.get()
kw={
'master':self.mainFrame
}
Label(text='User chose salad:',**kw).grid(row=1,column=1)
Label(text='%s'%chose_salad,**kw).grid(row=2,column=1)

self.root.bind_all('<Return>',self.endProcess)

def __call__(self):
self.root.bind_all('<Escape>',self.endProcess)
self.chooseSide()

if __name__ == '__main__':
Restaurant()()
[/CODE]

pbuk said:
what happens when you want to add another choice

In my case, I only have the user choose from two options.
 
Last edited: