Python/ Tkinter - 带有多个参数的 运行 函数的按钮不起作用
Python/ Tkinter - Button to run function with multiple arguments not working
我正在尝试编写一个程序来显示 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
命令,但我不确定它在这个函数中如何工作。
您走在正确的轨道上 - 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()
等)将 return 该小部件以供将来参考。然而,几何管理方法(grid()
、pack()
等)只是作用于它们的小部件和 return None
。这意味着您正在将 None
分配给 self.label1
、self.entry1
,依此类推。将小部件创建与几何管理分开:
self.label1 = Label(master, text="Entry 1")
self.label1.grid(row=0, sticky=E)
您现在可以使用实际的小部件。
正常的解决方案是让您的按钮调用特定于该按钮的函数。该函数的工作是收集数据,然后对数据进行操作:
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
获取值然后使用它们。
我正在尝试编写一个程序来显示 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
命令,但我不确定它在这个函数中如何工作。
您走在正确的轨道上 - 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()
等)将 return 该小部件以供将来参考。然而,几何管理方法(grid()
、pack()
等)只是作用于它们的小部件和 return None
。这意味着您正在将 None
分配给 self.label1
、self.entry1
,依此类推。将小部件创建与几何管理分开:
self.label1 = Label(master, text="Entry 1")
self.label1.grid(row=0, sticky=E)
您现在可以使用实际的小部件。
正常的解决方案是让您的按钮调用特定于该按钮的函数。该函数的工作是收集数据,然后对数据进行操作:
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
获取值然后使用它们。