【问题标题】:Python/ Tkinter - Button to run function with multiple arguments not workingPython / Tkinter - 运行具有多个参数的函数的按钮不起作用
【发布时间】:2015-11-10 10:12:14
【问题描述】:

我正在尝试编写一个程序,该程序将显示 4 行 2 列,第 0 列是标签,第 1 列是条目。然后,当单击按钮时,将这 4 个整数条目作为参数传递给函数。到目前为止,这是我的代码:

from tkinter import *

root = Tk()


class ClassName():

     def __init__(self, master):

       self.run_button = Button(self.master, text="Button Text", bg="green", fg="black", 
                               command="HERE IS WHERE I NEED HELP")
       self.run_button.grid(row=4, columnspan=2)

       self.label1 = Label(master, text="Entry 1").grid(row=0, sticky=E)
       self.label2 = Label(master, text="Entry 2").grid(row=1, sticky=E)
       self.label3 = Label(master, text="Entry 3").grid(row=2, sticky=E)
       self.label4 = Label(master, text="Entry 4").grid(row=3, sticky=E)

       self.entry1 = Entry(master).grid(row=0, column=1, sticky=W)
       self.entry2 = Entry(master).grid(row=1, column=1, sticky=W)
       self.entry3 = Entry(master).grid(row=2, column=1, sticky=W)
       self.entry4 = Entry(master).grid(row=3, column=1, sticky=W)

然后我想获取 4 个条目并将它们传递给一个名为 the_function 的不同函数。 the_function 所做的只是根据 4 个条目的值打印出一些内容。所以我剩下的代码是这样的:

def the_function(self, a, b, c, d):
#    Ensure a, b, c, and d are integers, 
#    do some math on the numbers and print something out based on the
#    values of a, b, c and d.

irrelevant_variable = ClassName(root)
root.mainloop()

该功能在没有 GUI 的情况下正常工作,但我无法弄清楚如何创建一个按钮,该按钮采用 self.entry1 并将其作为 a 传递给 the_function

其他帖子让我认为我应该使用lambda 命令,但我不确定它在这个函数中是如何工作的。

【问题讨论】:

  • should not assign a widget on the same line that you grid it。你在用教程吗?我正在尝试确定这个常见错误是否有单一来源,或者是否每个新用户都独立成为它的受害者。
  • 马克,请在评论中回复凯文的问题。请发布您正在使用的教程的链接,以便我们尝试防止其他人在将来遇到同样的问题。
  • @Kevin - 我通常不会错过几何方法链接的小部件分配,但我今天做到了。 :) 我会在我的回答中提到它。
  • 我引用的教程建议在我介绍它们的同一行上格式化小部件,该教程由 thenewboston 在 YouTube 上发布,标题为“Python GUI with Tkinter - 4 - Grid Layout”。也许我会更适合阅读完整的教程,然后接近该项目。有什么靠谱的教程推荐吗?
  • 从技术上讲,您可以执行此链接,它会显示小部件,但是当您想要返回其中一个小部件时它变得不合适,例如获取 Entry 小部件的内容.我喜欢Effbot,但这更像是偶尔提供示例的参考,而不是完整的教程。

标签: python button lambda tkinter multiple-arguments


【解决方案1】:

你在正确的轨道上 - lambda 允许你定义一个匿名的内联函数:

...command=lambda: the_function(entry1.get(), entry2.get(), entry3.get(), entry4.get())

它基本上充当包装器。你也可以这样做:

def mywrapper(self):
    the_function(entry1.get(), entry2.get(), entry3.get(), entry4.get())

然后将其绑定到按钮:

...command=self.mywrapper)

或者,只需让the_function 自己获取必要的变量:

def the_function(self):
    a = entry1.get()
    b = entry2.get()
    c = entry3.get()
    d = entry4.get()
    #    Ensure a, b, c, and d are integers

并在没有 lambda 的情况下绑定该函数:

...command=self.the_function)

但是,这对您当前的代码没有帮助 - 当您真正有兴趣引用小部件时,将几何管理方法链接到小部件创建中会导致问题。小部件构造函数(Button()Entry() 等)将返回该小部件以供将来参考。但是,几何管理方法(grid()pack() 等)只是作用于它们的小部件并返回 None。这意味着您将None 分配给self.label1self.entry1 等等。将小部件创建与几何管理分开:

self.label1 = Label(master, text="Entry 1")
self.label1.grid(row=0, sticky=E)

您现在可以使用实际的小部件。

【讨论】:

  • 我决定让the_function 获取值,然后通过command 参数显式调用它,并重新格式化小部件创建/操作并且它可以工作。谢谢。
【解决方案2】:

通常的解决方案是让您的按钮调用特定于该按钮的函数。该函数的工作是收集数据,然后对数据采取行动:

def __init__(...):
    ...
    self.run_button = Button(..., command=self.do_run)
    ...

def do_run(self):
    e1 = self.entry1.get()
    e2 = self.entry2.get()
    e3 = self.entry3.get()
    e4 = self.entry4.get()

    self.the_function(e1, e2, e3, e4)

您可以使用 lambda 或 functools.partial,但这会带来缺点而没有明显的优点。尽可能使用真正的函数而不是 lambda,您的代码将更易于编写、阅读和维护。

您也可以在the_function 中调用get() 方法。这个选择由你。如果the_function 可以在多个上下文中使用,那么将其与 UI 分离会很有用。如果唯一的目的是始终处理来自条目小部件的值,您可以跳过中间函数并简单地让 the_function 获取值然后使用它们。

【讨论】:

    猜你喜欢
    • 2019-07-18
    • 2013-03-06
    • 1970-01-01
    • 1970-01-01
    • 2019-07-28
    • 2022-01-23
    • 2021-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多