2015-08-17 7 views
2

Я пытаюсь написать программу, в которой будут отображаться 4 строки из 2 столбцов, причем столбец 0 является метками, а столбец 1 - это записи. Затем передайте эти 4 целых элемента через аргументы в функцию, когда нажата кнопка. Вот мой код до сих пор:Python/Tkinter - кнопка для запуска функции с несколькими аргументами не работает

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

Вы [не должны назначать виджет в той же строке, что вы 'grid' it] (http://stackoverflow.com/questions/1101750/tkinter-attributeerror-nonetype-object-has-no-attribute-get) , Вы используете учебник? Я пытаюсь определить, имеет ли эта распространенная ошибка один источник, или каждый новый пользователь становится жертвой этого независимо. – Kevin

+0

Марк, пожалуйста, ответьте на вопрос Кевина в комментарии здесь. Пожалуйста, разместите ссылку на учебник, который вы используете, чтобы мы могли помешать другим людям иметь такую ​​же проблему в будущем. –

+0

@Kevin - Я обычно не пропускаю задания виджетов с помощью цепочки геометрических методов, но я сделал это сегодня. :) Я упомянул об этом в своем ответе. – TigerhawkT3

ответ

3

Вы находитесь на правильном пути - 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) 

Теперь у вас есть реальные виджеты для работы с.

+0

Я решил, что 'the_function' получит значения, а затем вызовет их явно через параметр' command', а также переформатирует создание/манипуляцию виджета, и он работает. Спасибо. –

0

Обычное решение - чтобы ваша кнопка вызывала функцию, специфичную для этой кнопки. Работа функции заключается в сборе данных, а затем действовать по данным:

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) 

Вы можете использовать лямбда или functools.partial, но это приносит неудобства без каких-либо явных преимуществ. Ваш код будет легче писать, читать и поддерживать с помощью реальных функций, а не лямбда, когда это возможно.

Вы также можете вызвать методы get() внутри the_function. Выбор остается за вами. Если the_function можно использовать в нескольких контекстах, может оказаться полезным отключить его от пользовательского интерфейса. Если единственная цель - всегда обрабатывать значения из виджетов записи, вы можете пропустить промежуточную функцию и просто получить значения the_function, а затем использовать их.