Python/ Tkinter - кнопка для запуска функции с несколькими аргументами не работает
Я пытаюсь написать программу, которая будет отображать 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()
Функция работает правильно без графического интерфейса, но я не могу понять, как создать кнопку, которая принимает self.entry1
и передает его как a
в the_function
,
Другие посты заставили меня думать, что я должен использовать lambda
команда, но я не уверен, как это будет работать в рамках этой функции.
2 ответа
Вы на правильном пути - 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
И свяжите эту функцию без лямбды:
...command=self.the_function)
Тем не менее, это не поможет в вашем текущем коде - сцепление ваших методов управления геометрией с созданием виджета, когда вы на самом деле заинтересованы в ссылке на виджет, вызовет проблему. Конструкторы виджетов (Button()
, Entry()
и т. д.) вернет этот виджет для дальнейшего использования. Тем не менее, методы управления геометрией (grid()
, pack()
и т. д.) просто действуйте на свой виджет и возвращайте 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, но это приносит недостатки без явных преимуществ. Ваш код будет легче писать, читать и поддерживать, используя реальные функции, а не лямбда-выражения, когда это возможно.
Вы также можете позвонить get()
методы внутри the_function
, Выбор остается за вами. Если the_function
может использоваться в нескольких контекстах, может быть полезно отсоединить его от пользовательского интерфейса. Если единственная цель когда-либо состоит в том, чтобы всегда обрабатывать значения из виджетов ввода, вы можете пропустить промежуточную функцию и просто the_function
получить значения, а затем использовать их.