类中的tkinter按钮无法调用函数

时间:2018-02-05 02:16:13

标签: python tkinter

Total noob,严肃而愤怒地与Python挣扎......

我想做的事情应该很简单:

  1. 按一下按钮。
  2. 连接该按钮即可实现功能。
  3. 点击按钮 - >运行功能。
  4. 问题来自于我们必须使用CLASS(无论我阅读多少,研究 - 甚至付钱去上课对我来说都没有意义)...

    我已经尝试了将这个小的convert()函数放在类中,添加self.convert或root.convert的每个可以组合的组合 - 并且它的NONE工作。而且,我无能为力 - 或接下来要尝试什么。

    以下是代码:

    from tkinter import *
    from tkinter.ttk import Frame, Button, Style
    
    
    def convert():
        print("clicked")
        kg = entry_kg.get()
        print(kg)
    
    
    
    class Example(Frame):
    
        def __init__(self):
            super().__init__()
    
        self.initUI()    # initiate the GUI
        # -------------------------------
    
    
        def initUI(self):
    
            self.master.title("Weight Converter")
            self.pack(fill=BOTH, expand=True)
            # -------------------------------------
    
            frame_kg = Frame(self)   # frame for Kilograms
            frame_kg.pack(fill=X)
    
            lbl_kg = Label(frame_kg, text="Kilograms", width=16)
            lbl_kg.pack(side=LEFT, padx=5, pady=5)
    
            entry_kg = Entry(frame_kg)
            entry_kg.pack(fill=X, padx=(5, 30), expand=True)
            # ------------------------------------------------
    
            frame_btn = Frame(self)    # frame for buttons
            frame_btn.pack(fill=BOTH, expand=True, padx=20, pady=5)
    
            btn_convert=Button(frame_btn, text="Convert", command=convert)
            btn_convert.pack(side=LEFT, padx=5, pady=5)
    
            # -------------------------------------------
    
    def main():
    
        root = Tk()
        root.geometry("300x200+300+200")
        app = Example()
        root.mainloop()
    
    
    if __name__ == '__main__':
        main()
    

    我做错了什么?

    如何正确做到?

    一项看似随意而无用的简单任务的过度复杂化令人非常恼火......

3 个答案:

答案 0 :(得分:2)

如果你想让你的函数在类之外设计,但想要从类中定义的按钮调用它,解决方案是在类中创建一个方法,它接受输入值,然后将它们传递给外部功能。

这称为解耦。您的函数与UI的实现解耦,这意味着您可以在不更改函数的情况下完全更改UI的实现,反之亦然。它还意味着您可以在许多不同的程序中重用相同的功能而无需修改。

代码的整体结构应如下所示:

# this is the external function, which could be in the same
# file or imported from some other module
def convert(kg):
    pounds = kg * 2.2046
    return pounds

class Example(...):
    def initUI(self):
        ...
        self.entry_kg = Entry(...)
        btn_convert=Button(..., command=self.do_convert)
        ...

    def do_convert(self):
        kg = float(self.entry_kg.get())
        result = convert(kg)
        print("%d kg = %d lb" % (kg, result))

答案 1 :(得分:-1)

entry_kg方法范围之外的任何地方initUI 。这就是为什么。您可以通过替换:

将其从方法变量转换为实例属性,以便为类方法提供支持
entry_kg = Entry(frame_kg)
entry_kg.pack(fill=X, padx=(5, 30), expand=True)

使用:

self.entry_kg = Entry(frame_kg)
self.entry_kg.pack(fill=X, padx=(5, 30), expand=True)

只有然后

您可以在类方法中提及它:

...
kg = self.entry_kg.get()

如果您再次在convert下使用Example方法,那么就是这样:

def initUI(self):
...
def convert(self):           # is defined under the same scope as initUI
    print("clicked")
    kg = self.entry_kg.get() # notice that it now refers to self.e...
    print(kg)

也不要忘记替换命令选项:

btn_convert=Button(..., command=self.convert)

或仅然后

当在类范围之外时,通过在类创建的对象上使用点表示法:

def main():

    root = Tk()
    root.geometry("300x200+300+200")
    app = Example()
    kg = app.entry_kg.get() # This would return an empty string, but it would still be valid
    root.mainloop()

与全局方法一起使用,例如convert的当前状态,您需要使app(它是属性的对象)全局,或者将其显式传递给方法。< / p>

答案 2 :(得分:-1)

以下是您的代码的修改版本。所有CAPS行注释都显示了这些更改。我显然误解了你的问题(这可以说你可以弄清楚如何使convert()函数成为类的一部分。但是,你提到你想要与之相反,所以我在这里相应地修改了代码。 / p>

基本上问题归结为convert()函数需要访问在tkinter.Entry类中创建的Example窗口小部件 - 在这种情况下。{/ p>

这样做的一种方法是将窗口小部件保存在全局变量中,并通过分配给它的变量名访问它。许多人这样做是因为这是最容易做到的事情,但正如你应该知道的那样,全局变量被认为是一种不好的做法,通常是应该避免的。

有一种常见的方法可以避免需要使用tkinter,有时称为“the extra arguments trick”。要使用它,您需要做的就是使用一个定义了默认值的参数创建一个简短的匿名函数 - 在这种情况下,它将是您希望传递给现在“包裹”的Entry小部件{{1}功能。这可以使用所谓的lambda expression来完成。下面的修订代码及其中的注释显示并描述了如何执行此操作:

convert()