【问题标题】:Py 3: tkinter frames, coding inside or outside of frame classesPy 3:tkinter 帧,在帧类内部或外部编码
【发布时间】:2016-07-17 23:39:03
【问题描述】:

所以我正在使用 python 3 和 tkinter 为学校创建一个 GUI 数学程序,我们必须询问用户他们想要使用什么公式(加、减、乘、除),然后问 10 个问题显示结果页面一旦在该页面上回答了所有 10 个问题,然后循环重新开始。我想创造4个不同的困难

简单 = (1,9) 之间的范围,中等 = (10,24) 之间的范围,困难 = (25,50) 之间的范围,疯狂 = (51,100) 之间的范围

到目前为止,我已经创建了如下所示的 gui,但我想知道我是要在页面类中还是在类之外组织方程式的工作。我对 python/tkinter 很陌生,我以前从未使用过它,但刚刚了解了到目前为止我在 youtube 上观看的时间和时间。

我只想知道从现在开始到哪里放置方程式代码/公式。一旦我知道把它贴在哪里,它就会消失。

(如果您将以下所有代码复制并粘贴到 python 3 中并保存,它将立即生效。由于我将其全部复制到此聊天中,任何问题都将是复制和粘贴中的缩进。

您在下面看到的任何问题,请随时指出。正如我所说,我很新,我 Google 并没有真正提供帮助,因为我不太清楚要输入什么来找到它。

亲切的问候

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()

【问题讨论】:

    标签: python class user-interface python-3.x tkinter


    【解决方案1】:

    这里有一个例子让你了解*Vars的种类。

    from tkinter import *
    from tkinter.ttk import *
    
    
    class MainPanel(Frame):
        def __init__(self, master):
            Frame.__init__(self, master)
    
            # first setup two StringVars. They will be linked to a Label and an Entry widget.
            # we should keep a reference to these two StringVars, because we will call their method
            # to read/write widget content.
            self.msg2show = StringVar()
            self.text_input = StringVar()
    
            # this is a fixed Label widget whose display will no change.
            # No need to keep a reference(meaning to assign it to a variable).
            Label(self, text='If you click the button, the text in the entry widget will show above.').pack()
    
            # this is a variable Label widget whose display is decided by the linked variable `self.msg2show`
            Label(self, textvariable=self.msg2show).pack()
    
            # this is a variable Entry widget whose content is saved into `self.text_input`
            Entry(self, textvariable=self.text_input).pack()
    
            # this is the button who will trigger `self.set_msg` on click.
            Button(self, text='Set message', command=self.set_msg).pack()
    
        def set_msg(self):
            # get out what in the Entry widget through calling the `get()` method of `self.text_input`
            text_in_entry_widget = self.text_input.get()
            # and print it into console, for checking.
            print(text_in_entry_widget)
    
            # then we set that text into self.msg2show, and since it is linked with the variable Label widget
            # the display of that Label will then be set to text_in_entry_widget.
            self.msg2show.set(text_in_entry_widget)
    
            # You can see here I print the `text_in_entry_widget` to console as well as to a Label.
            # You can do it in the same way.
    
    if __name__ == '__main__':
        root = Tk()
        MainPanel(root).pack()
        root.mainloop()
    

    【讨论】:

    • 非常感谢。阅读这让我明白了很多,而且我实际上让它在每次提交时将答案显示为下面的标签!!!!你是个传奇!!感谢您提供的所有帮助!我看过 PyQt,但不幸的是,对于第 7 种形式的标准,我们没有大声使用 PyQT,我们不得不使用 tkinter。
    【解决方案2】:

    首先,那些难度选择的复选按钮所承载的逻辑可以用单选按钮代替。它会减少很多代码。

    其次,您可以将四个方程式页面共享的逻辑提取到一个基类中,并继承该基类以创建四个方程式页面。

    至于你的问题,我觉得可以放在基类的某个方法中,这是我修改的代码。

    《Python 编程》这本书很好地介绍了 tkinter,这个网站http://www.tcl.tk/man/tcl8.6/TkCmd/contents.htm 提供了 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()
    

    【讨论】:

    • 非常感谢您。你的编辑和我的工作背后的逻辑运行得更加顺畅。就像我说的那样,我对 tkinter 还是很陌生(今年才开始),所以这有很大帮助!我将完成代码,现在以更结构化的方式完成它:) 再次感谢您的帮助。我也很感激你留下的 cmets 解释了什么代码和/或它在那里做什么! :)
    • 嗨,我看到了你的困惑。如果您想在 GUI 上显示某些内容,最简单的方法是使用 Label 小部件。您可以设置一个 StringVar(),例如 self.msg2show = tk.StringVar(value='hello world'),然后将此变量链接到一个标签小部件:Lable(..., textvariable=self.msg2show, ...).pack()。然后您可以使用self.msg2show.set('new message will display on that label') 来更新标签小部件的内容。在这种情况下,该标签不再需要 text 参数。
    • 你能检查一下我坚持的新答案,以确保我这样做是正确的。 :)
    • 好吧,其实你应该把self.msg2show = tk.StringVar(...)放在EquationPageBase__init__方法中。你应该在它之后设置Label(self, textvariable=self.msg2show).pack(),不要使用Label=Label(...),如果我们之后不使用它,就不需要将Label小部件分配给变量。并使用self.msg2show.set('a message') 而不是 print('a message')(查看您注释掉的位置)。重试。将 *Var(StringVar, IntVar, FloatVar) 链接到一个小部件,然后您可以通过该 *Var 操作小部件,这就是 tkinter 的工作原理。
    • 好的,所以通过将self.msg2show.set('a message') 放在添加页面中是我想要的,但我希望它显示的是在submit definition 中生成的内容。所以标签将在提交按钮下方告诉用户他们是否正确,然后最后说做得好你从这么多中得到了这么多正确(因为我调整了上面的代码)不会放在EquationPageBase__init__ 中的那个函数破坏了从submit definition 获得答案的目的。抱歉,如前所述,我对 tkinter 和 python 还是很陌生.. :/
    猜你喜欢
    • 1970-01-01
    • 2023-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-28
    • 2020-05-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多