Search code examples
pythontkinterwidgetradio-button

How do I call the same function with tkinter?


I have a simple tkinter window with two radiobuttons. If I select 'Yes', a new line is added with two other radiobuttons. I try to use the same function every time I click 'Yes' but the radiobuttons are automatically selected if the mouse is moved onto them.

Here's my code:

from tkinter import *
import tkinter as tk

class Application(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)

        self.i = 1

        self.Frame1 = Frame(self)
        self.Frame1.grid(row=0, column=0)

        self.label = tk.Label(self.Frame1, text='Select Yes or No')
        self.label.grid(row=0, column=0)

        self.radioValueYesOrNo = tk.IntVar()
        self.RadiobuttonYesOrNo = tk.Radiobutton(self.Frame1, text='Yes',
                                                            variable=self.radioValueYesOrNo,
                                                            value=1,
                                                            command=self.addWidgets
                                                            )
        self.RadiobuttonYesOrNo.grid(row=0, column=1)
        
        self.RadiobuttonNonBoostPresent = tk.Radiobutton(self.Frame1, text='No',
                                                            variable=self.radioValueYesOrNo,
                                                            value=2)
        self.RadiobuttonNonBoostPresent.grid(row=0, column=2, padx=20)

    def addWidgets(self):
        valueRadioButton = self.returnValueRadiobutton()
        if valueRadioButton == 1:
            self.label = tk.Label(self.Frame1, text='Select Yes or No')
            self.label.grid(row=self.i, column=0)

            self.radioValueYesOrNo = tk.IntVar()
            self.RadiobuttonYesOrNo = tk.Radiobutton(self.Frame1, text='Yes',
                                                                variable=self.radioValueYesOrNo,
                                                                value=1,
                                                                command=self.addWidgets
                                                                )
            self.RadiobuttonYesOrNo.grid(row=self.i, column=1)
            self.RadiobuttonNonBoostPresent = tk.Radiobutton(self.Frame1, text='No',
                                                                variable=self.radioValueYesOrNo,
                                                                value=2)
            self.RadiobuttonNonBoostPresent.grid(row=self.i, column=2, padx=20)
            self.i = self.i+1

    def returnValueRadiobutton(self):
        return self.radioValueYesOrNo.get()

if __name__ == "__main__":
    app = Application()
    app.mainloop()

Does someone know how to fix this? Is this the best way to write the code?


Solution

  • Youre not too far off, however you would need to move your overwriting of self.i up so your .grid calls already use the updated value (edit: i was wrong, you use 0 initially and set i to 1, so this should be no issue). In general i advise you to use a list, dict or some kind where you store your widgets so you can access them later on. I think in your example you keep overwriting the same variables which is why it was messed up. I modified your code and added two optional parts where you delete the callbacks from checkboxes who already produced a new pair, or to even disable the old ones. However, i hope my solution is clear and helps you get going:

    from tkinter import *
    import tkinter as tk
    from functools import partial
    
    
    class Application(tk.Tk):
        def __init__(self):
            tk.Tk.__init__(self)
    
            self.i = 1
    
            self.Frame1 = Frame(self)
            self.Frame1.grid(row=0, column=0)
    
            self.label = tk.Label(self.Frame1, text='Select Yes or No')
            self.label.grid(row=0, column=0)
    
            self.values = []
            self.radiobuttons_yes = []
            self.radiobuttons_no = []
    
            self.add_radiobuttons()  # adds the first pair
    
        def add_radiobuttons(self):
            """Adds a new set of radiobuttons and appends radiobutton_callback with the current index as command"""
            self.values.append(tk.IntVar())
            self.radiobuttons_yes.append(tk.Radiobutton(self.Frame1, text='Yes',
                                                        variable=self.values[-1],
                                                        value=1,
                                                        command=partial(self.radiobutton_callback, len(self.values) - 1)))
            self.radiobuttons_yes[-1].grid(row=self.i, column=0)
            self.radiobuttons_no.append(tk.Radiobutton(self.Frame1, text='No',
                                                       variable=self.values[-1],
                                                       value=2,
                                                       command=partial(self.radiobutton_callback, len(self.values) - 1)))
            self.radiobuttons_no[-1].grid(row=self.i, column=1)
            self.i += 1
    
        def radiobutton_callback(self, index):
            """Callback function for the radiobuttons"""
            if self.values[index].get() == 1:
                # optional: delete command of current radiobuttons to prevent multiple calls
                self.radiobuttons_yes[index].config(command='')
                self.radiobuttons_no[index].config(command='')
    
                # # optional2: set previous radiobuttons to inactivate
                # self.radiobuttons_yes[index].config(state=DISABLED)
                # self.radiobuttons_no[index].config(state=DISABLED)
    
                # add new radiobuttons
                self.add_radiobuttons()
    
    
    if __name__ == "__main__":
        app = Application()
        app.mainloop()