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 получить значения, а затем использовать их.

Другие вопросы по тегам