Python Tkinter check radio button state before proceed
Question: I have this code which is working

    
    
    import Tkinter as tk
    from Tkinter import *
    
    
    LARGE_FONT= ("Verdana", 12)
    
    class ChangePages(tk.Tk):
    
        def __init__(self, *args, **kwargs):
    
            tk.Tk.__init__(self, *args, **kwargs)
            container = tk.Frame(self)
            container.pack()
            container.grid_rowconfigure(0, weight=1)
            container.grid_columnconfigure(0, weight=1)
            self.frames = {}
            for F in (MainPage, Page01, Page02):
    
                frame = F(container, self)
    
                self.frames[F] = frame
    
                frame.grid(row=0, column=0, sticky="nsew")
    
            self.show_frame(MainPage)
    
        def show_frame(self, cont):
    
            frame = self.frames[cont]
            frame.tkraise()
    
    #MainPage
    class MainPage(tk.Frame):
    
        def __init__(self, parent, controller):
            tk.Frame.__init__(self,parent)
    
            button1=Button(self,text='Go To Page 1',fg='blue',font=('Helvetica',26),height=5, width=20,command=lambda: controller.show_frame(Page01)).grid(row=1,column=1)
    
    #Page01
    class Page01(tk.Frame):
    
        def __init__(self, parent, controller):
    
            option1 = IntVar()
            option2 = IntVar()
            option3 = IntVar()
    
            tk.Frame.__init__(self, parent)
            f = Frame(self)
            f.pack(side='left')
    
            label1=Label(f,text='Select options',fg='blue', font=("Arial", 36, "bold"),width=54, relief='solid').grid(row=1,column=1,columnspan=3)
    
            labelspacing=Label(f,text='Option 1 ',font=("Arial", 18, "bold"),width=20,height=1).grid(row=2,column=1)
            labelspacing=Label(f,text='Option 2 ',font=("Arial", 18, "bold"),width=20,height=1).grid(row=2,column=2)
            labelspacing=Label(f,text='Option 3',font=("Arial", 18, "bold"),width=20,height=1).grid(row=2,column=3)
    
            buttonoption11=Radiobutton(f, text="Option 1 - A", variable=option1, value=1, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=3,column=1)
            buttonoption21=Radiobutton(f, text="Option 2 - A", variable=option2, value=1, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=3,column=2)
            buttonoption31=Radiobutton(f, text="Option 3 - A", variable=option3, value=1, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=3,column=3)
    
            buttonoption12=Radiobutton(f, text="Option 1 - B", variable=option1, value=2, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=4,column=1)
            buttonoption22=Radiobutton(f, text="Option 2 - B", variable=option2, value=2, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=4,column=2)
            buttonoption32=Radiobutton(f, text="Option 3 - B", variable=option3, value=2, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=4,column=3)
    
            buttonoption23=Radiobutton(f, text="Option 2 - C", variable=option2, value=3, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=5,column=2)
    
            buttonnback=Button(f,text='Back',fg='blue',font=('Helvetica',26),height=1,width=15,command=lambda: controller.show_frame(MainPage)).grid(row=10,column=1)
            buttonnext=Button(f,text='Next',fg='blue',font=('Helvetica',26),height=3,width=15,command=lambda: controller.show_frame(Page02)).grid(row=10,column=2)
    
    #Page02
    class Page02(tk.Frame):
    
        def __init__(self, parent, controller):
            tk.Frame.__init__(self, parent)
            label = tk.Label(self, text="Page 02!!!", font=LARGE_FONT)
            label.pack(pady=10,padx=10)
    
            button1 = tk.Button(self, text="Back to Home",
                                command=lambda: controller.show_frame(MainPage))
            button1.pack()
    
            button2 = tk.Button(self, text="Page 01",
                                command=lambda: controller.show_frame(PageSub35t))
            button2.pack()
    
    
    #Root loop
    app = ChangePages()
    app.mainloop()
    

What I want to do is:

When the user presses next in pag01, I want to check the states of radio
buttons. For example if the user chose "Option 1 -A" and "Option 2 -C", I want
to popup a message saying "You are not allowed to choose 2c! You can choose 2c
only if 1B is selected" and not let him to go to page02.


Answer: I understand your problem and how you want to solve it. But, from an user
experience point of view there is a better way of doing this. Instead of
showing the user options that the user can't choose and displaying error
messages, it is better to **only show the user what he can choose**. Scenario
example:

> User selected Option 1 -A
>
> The Radio button Option 2 -C turns grey(disabled)

Here is a demo:

    
    
    #very bad code
    #http://stackoverflow.com/questions/28900100/python-tkinter-check-radio-button-state-before-proceed/28901595#28901595
    
    try:#3.X
        import tkinter as tk
    except ImportError:#2.X
        import Tkinter as tk
    
    #use ttk cascade style techniques instead !!!
    LARGE_FONT= ("Verdana", 12)
    
    class ChangePages(tk.Tk):
    
        def __init__(self, *args, **kwargs):
    
            tk.Tk.__init__(self, *args, **kwargs)
            container = tk.Frame(self)
            container.pack() #use grid everywhere
            container.grid_rowconfigure(0, weight=1)
            container.grid_columnconfigure(0, weight=1)
            self.frames = {}
            for F in (MainPage, Page01, Page02):
    
                frame = F(container, self)
    
                self.frames[F] = frame
    
                frame.grid(row=0, column=0, sticky="nsew")
    
            self.show_frame(MainPage)
    
        def show_frame(self, cont):
    
            frame = self.frames[cont]
            frame.tkraise()
    
    class MainPage(tk.Frame):
    
        def __init__(self, parent, controller):
            tk.Frame.__init__(self,parent)
    
            button1 = tk.Button(self,text='Go To Page 1',fg='blue',font=('Helvetica',26),height=5, width=20,command=lambda: controller.show_frame(Page01)).grid(row=1,column=1)
    
    class Page01(tk.Frame):
    
        def __init__(self, parent, controller):
    
            option1 = tk.IntVar()
            option2 = tk.IntVar()
            option3 = tk.IntVar()
    
            tk.Frame.__init__(self, parent)
            f = tk.Frame(self)
            f.pack(side='left')
    
            label1 = tk.Label(f,text='Select options',fg='blue', font=("Arial", 36, "bold"),width=54, relief='solid').grid(row=1,column=1,columnspan=3)
    
            #not used
            #labelspacing = tk.Label(f,text='Option 1 ',font=("Arial", 18, "bold"),width=20,height=1).grid(row=2,column=1)
            #labelspacing = tk.Label(f,text='Option 2 ',font=("Arial", 18, "bold"),width=20,height=1).grid(row=2,column=2)
            #labelspacing = tk.Label(f,text='Option 3',font=("Arial", 18, "bold"),width=20,height=1).grid(row=2,column=3)
    
            buttonoption21 = tk.Radiobutton(f, text="Option 2 - A", variable=option2, value=1, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20)
            buttonoption21.grid(row=3,column=2)
            buttonoption22 = tk.Radiobutton(f, text="Option 2 - B", variable=option2, value=2, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20)
            buttonoption22.grid(row=4,column=2)
            buttonoption32 = tk.Radiobutton(f, text="Option 3 - B", variable=option3, value=2, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20)
            buttonoption32.grid(row=4,column=3)
    
            buttonoption23 = tk.Radiobutton(f, text="Option 2 - C", variable=option2, value=3, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20)
            buttonoption23.grid(row=5,column=2)
    
            # this entire list is affected by switch_all_button()
            list_conditional = [buttonoption21, buttonoption22, buttonoption32, buttonoption23]
    
    
            def switch_button(button, active=True):
                if button is not None:
                    button['state'] = {True: tk.NORMAL, False: tk.DISABLED}[active]
                    #here you can also unselect
    
            def switch_all_button(active=True):
                for button in list_conditional:
                    switch_button(button, active=active)
    
            def after_option_command(what_button_should_be_disabled=None):
                def after_option():
                    switch_all_button(active=True)
                    switch_button(what_button_should_be_disabled, active=False)
                return after_option
    
    
            # to update the state of other buttons after 1 is pressed
            # use command=after_option_command(button_x) in the constructor
            buttonoption11 = tk.Radiobutton(f, command=after_option_command(buttonoption23), text="Option 1 - A", variable=option1, value=1, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20)
            buttonoption11.grid(row=3,column=1)
            buttonoption12 = tk.Radiobutton(f, command=after_option_command(), text="Option 1 - B", variable=option1, value=2, indicatoron=0, fg='blue',font=('Helvetica',26),height=1, width=20)
            buttonoption12.grid(row=4,column=1)
    
    
    
            buttonnback = tk.Button(f,text='Back',fg='blue',font=('Helvetica',26),height=1,width=15,command=lambda: controller.show_frame(MainPage)).grid(row=10,column=1)
            buttonnext = tk.Button(f,text='Next',fg='blue',font=('Helvetica',26),height=3,width=15,command=lambda: controller.show_frame(Page02)).grid(row=10,column=2)
    
    class Page02(tk.Frame):
    
        def __init__(self, parent, controller):
            tk.Frame.__init__(self, parent)
            label = tk.Label(self, text="Page 02!!!", font=LARGE_FONT)
            label.pack(pady=10,padx=10)
    
            button1 = tk.Button(self, text="Back to Home",
                                command=lambda: controller.show_frame(MainPage))
            button1.pack()
    
            button2 = tk.Button(self, text="Page 01",
                                command=lambda: controller.show_frame(PageSub35t))
            button2.pack()
    
    
    #Root loop
    app = ChangePages()
    app.mainloop()
    

You don't need to import tkinter twice. Use this syntax

    
    
    try:  # 3.X
        import tkinter as tk
    except ImportError:  # 2.X
        import Tkinter as tk
    

will force you to use `tk.` every time you are using a tkinter object explicit
better than implicit. It will also work with Python 3.

    
    
    #Page02
    class Page02(tk.Frame):
    

this is a useless comment because it doesn't add value. The code is poor
quality, but here's how to fix it:

  * Follow PEP8
  * Do not use classes as keys for dicts
  * Instead of describing the look inside your main code, do it outside or on top of the file using `ttk` and `ttk.Style()`
  * Widget.grid method returns None, which means 

`buttonoption11 = tk.Radiobutton(f,
command=after_option_command(buttonoption23), text="Option 1 - A",
variable=option1, value=1, indicatoron=0,
fg='blue',font=('Helvetica',26),height=1, width=20).grid(row=3,column=1)`

    * buttonoption11 is not a `tk.Radiobutton` but `None`
    * use .grid everywhere unless you have a very good reason not to
    * use for loops to create similar widgets

**Warning** the code I gave is not fixed, do not use it before you apply all
tips given above

edit: works as expected in the comment, read the comments to extend the API

