Search code examples
pythonpython-3.xtkinterradio-buttontkinter-entry

Tkinter changing entry state based on radiobutton


I have four radio buttons. Underneath these four button is an Entry widget. I am trying to make this Entry widget only become available to type into when the last radio button is selected. The gui is in a class, as you can see in the code below:

class Gui:
    def __init__(self):
        pass

    def draw(self):
        global root

        if not root:
            root  = tk.Tk()
            root.geometry('280x350')

            self.type = tk.StringVar()
            self.type_label = tk.Label(text="Game Mode")
            self.name_entry = tk.Entry()
            self.name_entry.configure(state="disabled")
            self.name_entry.update()
            self.type_entry_one = tk.Radiobutton(text="Garage", value="garage", variable=self.type, command=self.disable_entry(self.name_entry))
            self.type_entry_two = tk.Radiobutton(text="Festival", value="festival", variable=self.type, command=self.disable_entry(self.name_entry))
            self.type_entry_three = tk.Radiobutton(text="Studio", value="studio", variable=self.type, command=self.disable_entry(self.name_entry))
            self.type_entry_four = tk.Radiobutton(text="Rockslam", value="rockslam", variable=self.type, command=self.enable_entry(self.name_entry))
            
         
            self.type_label.pack()
            self.type_entry_one.pack()
            self.type_entry_two.pack()
            self.type_entry_three.pack()
            self.type_entry_four.pack()
            self.name_entry.pack()

            root.mainloop()

    def enable_entry(self, entry):
        entry.configure(state="normal")
        entry.update()

    def disable_entry(self, entry):
        entry.configure(state="disabled")
        entry.update()





if __name__ == '__main__':
    root = None
    gui = Gui()
    gui.draw()

However, the the self.name_entry is always available to type into. What am I doing wrong. If you still don't understand what is happening then please run this code yourself and you will see.

Thank you very much for your time and I look forward to responses.


Solution

  • You have the right idea about using the RadioButton to enable/disable the entry widget. Mostly it is your class design that is flawed - it is halfway between OO code, and procedural code...

    I fixed the class structure and made it a subclass of tk.Tk so it completely encapsulate your GUI. The name_entry is now enabled only when type_entry_four radio button is selected, and disabled otherwise. I've set that last button to be selected at launch, but you can easily change that; it results in the entry being enabled at launch.
    Superfluous variable passing through methods was removed, as was the draw method and the calls to it; all widget creation is now conveniently found in GUI.__init__

    import tkinter as tk
    
    
    class Gui(tk.Tk):
        def __init__(self):
            super().__init__()
            self.geometry('280x350')
    
            self.select_type = tk.StringVar()
            self.type_label = tk.Label(self, text='Game Mode')
            self.name_entry = tk.Entry(self)
            self.type_entry_one = tk.Radiobutton(self, text='Garage', value='garage', variable=self.select_type, command=self.disable_entry)
            self.type_entry_two = tk.Radiobutton(self, text='Festival', value='festival', variable=self.select_type, command=self.disable_entry)
            self.type_entry_three = tk.Radiobutton(self, text='Studio', value='studio', variable=self.select_type, command=self.disable_entry)
            self.type_entry_four = tk.Radiobutton(self, text='Rockslam', value='rockslam', variable=self.select_type, command=self.enable_entry)
    
            self.select_type.set('rockslam')   # select the last radiobutton; also enables name_entry
            
            self.type_label.pack()
            self.type_entry_one.pack()
            self.type_entry_two.pack()
            self.type_entry_three.pack()
            self.type_entry_four.pack()
            self.name_entry.pack()
    
        def enable_entry(self):
            self.name_entry.configure(state='normal')
    
        def disable_entry(self):
            self.name_entry.configure(state='disabled')
    
    
    if __name__ == '__main__':
        
        Gui().mainloop()