Py 3: tkinter frames, coding inside or outside of frame classes
Question: So I'm creating a GUI mathematical program for school using python 3 and
tkinter where we have to ask the user what formula they want to use (add, sub,
multiply, divide) and then ask 10 questions show a results page once all 10
questions have been answered on that page and then start over again in a loop.
i want to create 4 different difficulties

Easy = Range between (1,9), medium = Range between (10,24), Hard = Range
between (25,50), Insane = Range Between (51,100)

I've created the gui so far as shown below but want to know if I'm going to
organize the working out of the equations in the page classes or somehow
outside of the class. im pretty new to python/tkinter I've never used it
before but just learnt what i have so far off youtube hours and hours of
watching.

All i want to know is where to go from now with where to place the equation
code/formula. once i know where to stick it ill be away.

(all code below if you copy and paste into python 3 and save it will instantly
work. any problems will be indents from the copy and paste due to how i copied
it all into this chat.

Any issues you see below please feel free to point out. As I said I'm pretty
new I Google didn't really help as I didn't quite know what to type in to find
it.

kind regards

    
    
    import tkinter as tk
    from tkinter import *
    from tkinter import ttk #css kind of thing for tkinter
    import random
    
    difficulty = []
    
    LARGE_FONT = ("Times New Roman", 25)
    MEDIUM_FONT = ("Times New Roman", 15)
    SMALL_FONT = ("Times New Roman", 10)
    
    
    ###Base Code For Pages
    
    
    class ourprogramclass(tk.Tk):
    
        def __init__ (self, *args, **kwargs):
    
            tk.Tk.__init__(self, *args, **kwargs)
    
            tk.Tk.iconbitmap(self, default="mathsicon.ico")
            tk.Tk.wm_title(self, "Mathematic Equation program")
    
            container = tk.Frame(self)
            container.pack(side="top", fill="both", expand=True)
            container.grid_rowconfigure(0, weight=1)
            container.grid_columnconfigure(0, weight=1)
    
            self.frames = {}
    
            for F in (StartPage, AdditionPage, SubtractionPage, MultiplicationPage, DivisionPage ):
    
                frame = F(container, self)
    
                self.frames[F] = frame
    
                frame.grid(row=0, column=0, sticky="nsew")
    
            self.show_frame(StartPage)
    
        def show_frame(self, cont):
    
            frame = self.frames[cont]
            frame.tkraise()
    
    
    ###Page Classes front page
    
    
    
    class StartPage(tk.Frame):
    
        def __init__(self, parent, controller):
            tk.Frame.__init__(self,parent)
            label1 = tk.Label(self, text = "Mathmatics Problems Quiz", font=LARGE_FONT)
            label2 = tk.Label(self, text = "Mathematic Equation program", font=MEDIUM_FONT)
            label3 = tk.Label(self, text = "Select Your Operation and Difficulty Level", font=SMALL_FONT)
            label1.pack(pady=10,padx=10)
            label2.pack(pady=10,padx=10)
            label3.pack(pady=10,padx=10)
    
            button1 = tk.Button(self, text = "Addition Equations", font=MEDIUM_FONT,command=lambda: controller.show_frame(AdditionPage)).pack(fill=X)
            label = Label(self,text="").pack()
            button2 = tk.Button(self, text = "Subtraction Equations", font=MEDIUM_FONT,command=lambda: controller.show_frame(SubtractionPage)).pack(fill=X)
            label = Label(self,text="").pack()        
            button3 = tk.Button(self, text = "Multiplication Equations", font=MEDIUM_FONT,command=lambda: controller.show_frame(MultiplicationPage)).pack(fill=X)
            label = Label(self,text="").pack()
            button4 = tk.Button(self, text = "Division Equations", font=MEDIUM_FONT,command=lambda: controller.show_frame(DivisionPage)).pack(fill=X)
            label = Label(self,text="").pack()
    
            label4 = tk.Label(self, text = "Select Difficulty", font=LARGE_FONT).pack()
    
            def checkbutton_value1():
                if (var1.get()):
                    var2.set(0)
                    var3.set(0)
                    var4.set(0)
                    del difficulty[:]
                    difficulty.append(1)
                    print (difficulty[0])
    
            def checkbutton_value2():
                if(var2.get()):
                    var1.set(0)
                    var3.set(0)
                    var4.set(0)
                    del difficulty[:]
                    difficulty.append(2)
                    print (difficulty[0])
    
            def checkbutton_value3():
                if(var3.get()):
                    var1.set(0)
                    var2.set(0)
                    var4.set(0)
                    del difficulty[:]
                    difficulty.append(3)
                    print (difficulty[0])
    
            def checkbutton_value4():
                if(var4.get()):
                    var1.set(0)
                    var2.set(0)
                    var3.set(0)
                    del difficulty[:]
                    difficulty.append(4)
                    print (difficulty[0])
    
            var1 = IntVar()
            dif_button1 = tk.Checkbutton(self, text="Easy", variable=var1, command=checkbutton_value1).pack()
    
            var2 = IntVar()
            dif_button2 = tk.Checkbutton(self, text="Medium", variable=var2, command=checkbutton_value2).pack()
    
            var3 = IntVar()
            dif_button3 = tk.Checkbutton(self, text="Hard  ", variable=var3, command=checkbutton_value3).pack()
    
            var4 = IntVar()
            dif_button4 = tk.Checkbutton(self, text="Insane", variable=var4, command=checkbutton_value4).pack()
    
            quit_button = tk.Button(self, text='Quit', command=quit, font=MEDIUM_FONT).pack(fill=X, side = BOTTOM)
    
    
    ###Addition Page
    
    class AdditionPage(tk.Frame):
    
        def __init__(self, parent, controller):
    
    
            tk.Frame.__init__(self,parent)
            label1 = tk.Label(self, text = "Mathmatics Problems Quiz", font=LARGE_FONT).pack(pady=10,padx=10)
            label2 = tk.Label(self, text = "Mathematic Equation program", font=MEDIUM_FONT).pack(pady=10,padx=10)
            label3 = tk.Label(self, text = "You have Selected Addition as The Unit", font=SMALL_FONT).pack(pady=10,padx=10)
            button1 = tk.Button(self, text = "Reselect Unit", font=MEDIUM_FONT,command=lambda: controller.show_frame(StartPage)).pack(fill=X)
    
            label = Label(self,text="").pack()
            label = Label(self,text="").pack()
    
            #-----THIS IS WHERE I WANT THE EQUATION TO SHOW IN THE LABEL BELOW-----#
    
            question_label = Label(self, text="Enter Your Answer", font=MEDIUM_FONT ).pack()
            label = Label(self,text="").pack()
    
            self.entrytext = StringVar()
            Entry(self, textvariable=self.entrytext, font=MEDIUM_FONT,).pack(fill=X)
    
            label = Label(self,text="").pack()
            label = Label(self,text="").pack()
            submit_button = tk.Button(self, text = "Submit Answer", font=MEDIUM_FONT).pack(fill=X)
    
            quit_button = tk.Button(self, text='Quit', command=quit, font=MEDIUM_FONT,).pack(fill=X, side = BOTTOM)
    
    ####Subtraction Page
    
    class SubtractionPage(tk.Frame):
    
        def __init__(self, parent, controller):
            tk.Frame.__init__(self,parent)
            label1 = tk.Label(self, text = "Mathmatics Problems Quiz", font=LARGE_FONT).pack(pady=10,padx=10)
            label2 = tk.Label(self, text = "Mathematic Equation program", font=MEDIUM_FONT).pack(pady=10,padx=10)
            label3 = tk.Label(self, text = "You have Selected Subtraction as The Unit", font=SMALL_FONT).pack(pady=10,padx=10)
            button1 = tk.Button(self, text = "Reselect Unit", font=MEDIUM_FONT,command=lambda: controller.show_frame(StartPage)).pack(fill=X)
    
            label = Label(self,text="").pack()
            label = Label(self,text="").pack()
    
            #-----THIS IS WHERE I WANT THE EQUATION TO SHOW IN THE LABEL BELOW-----#
    
            question_label = Label(self, text="Enter Your Answer", font=MEDIUM_FONT ).pack()
            label = Label(self,text="").pack()
    
            self.entrytext = StringVar()
            Entry(self, textvariable=self.entrytext, font=MEDIUM_FONT,).pack(fill=X)
    
            label = Label(self,text="").pack()
            label = Label(self,text="").pack()
            submit_button = tk.Button(self, text = "Submit Answer", font=MEDIUM_FONT).pack(fill=X)
    
            quit_button = tk.Button(self, text='Quit', command=quit, font=MEDIUM_FONT,).pack(fill=X, side = BOTTOM)
    
    ###Multiply Page
    
    class MultiplicationPage(tk.Frame):
    
        def __init__(self, parent, controller):
            tk.Frame.__init__(self,parent)
            label1 = tk.Label(self, text = "Mathmatics Problems Quiz", font=LARGE_FONT).pack(pady=10,padx=10)
            label2 = tk.Label(self, text = "Mathematic Equation program", font=MEDIUM_FONT).pack(pady=10,padx=10)
            label3 = tk.Label(self, text = "You have Selected Multiplication as The Unit", font=SMALL_FONT).pack(pady=10,padx=10)
            button1 = tk.Button(self, text = "Reselect Unit", font=MEDIUM_FONT,command=lambda: controller.show_frame(StartPage)).pack(fill=X)
    
            label = Label(self,text="").pack()
            label = Label(self,text="").pack()
    
            #-----THIS IS WHERE I WANT THE EQUATION TO SHOW IN THE LABEL BELOW-----#
    
            question_label = Label(self, text="Enter Your Answer", font=MEDIUM_FONT ).pack()
            label = Label(self,text="").pack()
    
            self.entrytext = StringVar()
            Entry(self, textvariable=self.entrytext, font=MEDIUM_FONT,).pack(fill=X)
    
            label = Label(self,text="").pack()
            label = Label(self,text="").pack()
            submit_button = tk.Button(self, text = "Submit Answer", font=MEDIUM_FONT).pack(fill=X)
    
            quit_button = tk.Button(self, text='Quit', command=quit, font=MEDIUM_FONT,).pack(fill=X, side = BOTTOM)
    
    ###Division Page
    
    class DivisionPage(tk.Frame):
    
        def __init__(self, parent, controller):
            tk.Frame.__init__(self,parent)
            label1 = tk.Label(self, text = "Mathmatics Problems Quiz", font=LARGE_FONT).pack(pady=10,padx=10)
            label2 = tk.Label(self, text = "Mathematic Equation program", font=MEDIUM_FONT).pack(pady=10,padx=10)
            label3 = tk.Label(self, text = "You have Selected Division as The Unit", font=SMALL_FONT).pack(pady=10,padx=10)
            button1 = tk.Button(self, text = "Reselect Unit", font=MEDIUM_FONT,command=lambda: controller.show_frame(StartPage)).pack(fill=X)
    
            label = Label(self,text="").pack()
            label = Label(self,text="").pack()
    
            #-----THIS IS WHERE I WANT THE EQUATION TO SHOW IN THE LABEL BELOW-----#
    
            question_label = Label(self, text="Enter Your Answer", font=MEDIUM_FONT ).pack()
            label = Label(self,text="").pack()
    
            self.entrytext = StringVar()
            Entry(self, textvariable=self.entrytext, font=MEDIUM_FONT,).pack(fill=X)
    
            label = Label(self,text="").pack()
            label = Label(self,text="").pack()
            submit_button = tk.Button(self, text = "Submit Answer", font=MEDIUM_FONT).pack(fill=X)
    
            quit_button = tk.Button(self, text='Quit', command=quit, font=MEDIUM_FONT,).pack(fill=X, side = BOTTOM)
    
    
    
    app = ourprogramclass()
    app.mainloop()
    


Answer: First, the logic carried by those checkbuttons for difficulty selection can be
replaced by radio button. It will reduce much code.

Second, you can extract the logic shared by the four equation pages into a
base class, and inherit that base class to create the four equation pages.

As for your question, I think it can be put in some method of the base class,
this is the code I modified.

The book [Programming Python] covers tkinter very well, and this website
<http://www.tcl.tk/man/tcl8.6/TkCmd/contents.htm> provides details for tk.

    
    
    import tkinter as tk
    from tkinter import *
    from tkinter import ttk #css kind of thing for tkinter
    import random
    
    dif_enum = ['Easy', 'Medium', 'Hard', 'Insane']
    current_difficulty = dif_enum[0]
    
    NUM_QUESTIONS = 10
    
    LARGE_FONT = ("Times New Roman", 25)
    MEDIUM_FONT = ("Times New Roman", 15)
    SMALL_FONT = ("Times New Roman", 10)
    
    
    ###Base Code For Pages
    class ourprogramclass(tk.Tk):
    
        def __init__ (self, *args, **kwargs):
    
            tk.Tk.__init__(self, *args, **kwargs)
    
            # tk.Tk.iconbitmap(self, default="mathsicon.ico")
            tk.Tk.wm_title(self, "Mathematic Equation program")
    
            container = tk.Frame(self)
            container.pack(side="top", fill="both", expand=True)
            container.grid_rowconfigure(0, weight=1)
            container.grid_columnconfigure(0, weight=1)
    
            self.frames = {}
    
            for F in (StartPage, AdditionPage, SubtractionPage, MultiplicationPage, DivisionPage ):
    
                frame = F(container, self)
    
                self.frames[F] = frame
    
                frame.grid(row=0, column=0, sticky="nsew")
    
            self.show_frame(StartPage)
    
        def show_frame(self, cont):
    
            frame = self.frames[cont]
            frame.tkraise()
    
    
    ###Page Classes front page
    class StartPage(tk.Frame):
    
        def __init__(self, parent, controller):
            tk.Frame.__init__(self,parent)
            label1 = tk.Label(self, text = "Mathmatics Problems Quiz", font=LARGE_FONT)
            label2 = tk.Label(self, text = "Mathematic Equation program", font=MEDIUM_FONT)
            label3 = tk.Label(self, text = "Select Your Operation and Difficulty Level", font=SMALL_FONT)
            label1.pack(pady=10,padx=10)
            label2.pack(pady=10,padx=10)
            label3.pack(pady=10,padx=10)
    
            button1 = tk.Button(self, text = "Addition Equations", font=MEDIUM_FONT,command=lambda: controller.show_frame(AdditionPage)).pack(fill=X)
            label = Label(self,text="").pack()
            button2 = tk.Button(self, text = "Subtraction Equations", font=MEDIUM_FONT,command=lambda: controller.show_frame(SubtractionPage)).pack(fill=X)
            label = Label(self,text="").pack()
            button3 = tk.Button(self, text = "Multiplication Equations", font=MEDIUM_FONT,command=lambda: controller.show_frame(MultiplicationPage)).pack(fill=X)
            label = Label(self,text="").pack()
            button4 = tk.Button(self, text = "Division Equations", font=MEDIUM_FONT,command=lambda: controller.show_frame(DivisionPage)).pack(fill=X)
            label = Label(self,text="").pack()
    
            label4 = tk.Label(self, text = "Select Difficulty", font=LARGE_FONT).pack()
    
            # @etuc_comment:Use `Radiobutton` for the "select one from many" logic. It takes only a few lines.
            difficulty = tk.StringVar(value=dif_enum[0])
    
            def show_and_set_difficulty():
                global current_difficulty
                current_difficulty = difficulty.get()
                print(1 + dif_enum.index(difficulty.get()), difficulty.get())
    
            for dif in dif_enum:
                tk.Radiobutton(self, text=dif, value=dif, variable=difficulty, command=show_and_set_difficulty).pack()
    
            quit_button = tk.Button(self, text='Quit', command=quit, font=MEDIUM_FONT).pack(fill=X, side = BOTTOM)
    
    
    class EquationPageBase(tk.Frame):
        def __init__(self, parent, controller, equal_type):
            tk.Frame.__init__(self,parent)
            tk.Label(self, text="Mathmatics Problems Quiz", font=LARGE_FONT).pack(pady=10,padx=10)
            tk.Label(self, text="Mathematic Equation program", font=MEDIUM_FONT).pack(pady=10,padx=10)
            # @etuc_comment: Use the third parameter `equal_type` for displaying current equation type.
            tk.Label(self, text="You have Selected {} as The Unit".format(equal_type), font=SMALL_FONT).pack(pady=10,padx=10)
    
            tk.Button(self, text="Reselect Unit", font=MEDIUM_FONT,command=lambda: controller.show_frame(StartPage)).pack(fill=X)
    
            Label(self,text="").pack()
            Label(self,text="").pack()
    
            #-----THIS IS WHERE I WANT THE EQUATION TO SHOW IN THE LABEL BELOW-----#
            self.submit_counter = 0
            self.correct_counter = 0
            self.equation_strvar = tk.StringVar(value='')
            Label(self, textvariable=self.equation_strvar, font=MEDIUM_FONT).pack()
            Label(self,text="").pack()
    
            self.answer_strvar = StringVar()
            Entry(self, textvariable=self.answer_strvar, font=MEDIUM_FONT, ).pack(fill=X)
    
            Label(self,text="").pack()
            Label(self,text="").pack()
            tk.Button(self, text="Submit Answer", font=MEDIUM_FONT, command=self.submit).pack(fill=X)
    
            tk.Button(self, text='Quit', command=quit, font=MEDIUM_FONT,).pack(fill=X, side = BOTTOM)
    
            self.update_equation()
    
        def update_equation(self):
            self.equation = self.gen_equal()
            self.equation_strvar.set('Enter Your Answer For: {}'.format(self.equation))
            self.answer_strvar.set('')
    
        def gen_equal(self):
            """
            Subclasses will overload this method to generate the proper equation according to difficulty and
            equation type setting. See an example in the `AdditionPage`
            :return: Should return the equation as string. e.g. "1 + 2"
            """
            pass
    
        def submit(self):
            try:
                user_answer = int(self.answer_strvar.get())
            except:
                return
    
            if eval(self.equation) == user_answer:
                print('Correct')
                self.correct_counter += 1
            else:
                print('Error: {} != {}, answer is {}'.format(self.equation, user_answer, eval(self.equation)))
    
            self.submit_counter += 1
            if self.submit_counter < NUM_QUESTIONS:
                self.update_equation()
            else:
                self.show_result()
    
                self.submit_counter = 0
                self.correct_counter = 0
    
        def show_result(self):
            print('{} questions, {} correct.'.format(NUM_QUESTIONS, self.correct_counter))
    
    
    # Addition Page
    class AdditionPage(EquationPageBase):
        def __init__(self, parent, controller):
            EquationPageBase.__init__(self, parent, controller, equal_type='Addition')
    
        def gen_equal(self):
            """
            This is an example for addition.
            """
            if current_difficulty == 'Easy':
                return '{} + {}'.format(random.randint(1, 10), random.randint(1, 10))
            elif current_difficulty == 'Medium':
                return '{} + {}'.format(random.randint(10, 25), random.randint(10, 25))
            elif current_difficulty == 'Hard':
                return '{} + {}'.format(random.randint(25, 50), random.randint(25, 50))
            elif current_difficulty == 'Insane':
                return '{} + {}'.format(random.randint(50, 100), random.randint(50, 100))
            else:
                raise ValueError('Wrong difficulty')
    
    
    # Subtraction Page
    class SubtractionPage(EquationPageBase):
        def __init__(self, parent, controller):
            EquationPageBase.__init__(self, parent, controller, equal_type='Subtraction')
    
        def gen_equal(self):
            pass
    
    
    # Multiply Page
    class MultiplicationPage(EquationPageBase):
        def __init__(self, parent, controller):
            EquationPageBase.__init__(self, parent, controller, equal_type='Multiplication')
    
        def gen_equal(self):
            pass
    
    
    # Division Page
    class DivisionPage(EquationPageBase):
        def __init__(self, parent, controller):
            EquationPageBase.__init__(self, parent, controller, equal_type='Division')
    
        def gen_equal(self):
            pass
    
    
    app = ourprogramclass()
    app.mainloop()
    

