2013-06-06 3 views
2

У меня есть общий обратный вызов для ряда кнопок. После вызова callback я хочу идентифицировать вызывающего абонента по его ранее назначенному имени. Но я не мог понять в документации Tkinter, как я мог это сделать. Есть идеи?Как я могу получить имя виджета в Tkinter?

Моя программа ок.

def callback(event): 
    event.widget['text'] # 'name' does not work so 
         # I have to use the label of the button now, but it is a dirty solution. 

root.bind("<Button-1>", cb_button) 

Мне нужны имена, потому что я загружаю GUI из JSON с помощью pytkgen.

UPDATE: решение
Джастина выглядит красиво, но почему следующий код печати всегда 9 независимо от того, какая кнопка нажата?

def cb_button(i): 
    print i 

buttons = [('btn'+str(i), i) for i in range(10)] 
for (b, i) in buttons: 
    root.button(b, lambda: cb_button(i)) 
+2

Что вы подразумеваете под «ранее назначенным именем»? AFAIK, Tkinter [имена виджетов сами по себе] (http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/window-names.html). Программист не имеет возможности назначить их. – Kevin

+1

Зачем вам нужно имя? Что делает для вас то, что эта ссылка не делает? –

+0

Thx для беспокойства, я обновил свой вопрос. Я не хочу проверять все кнопки, чтобы выбрать, на какой из них я нажал. –

ответ

3

Основываясь на обновлении на ваш вопрос, я думаю, что понимаю проблему. У вас есть файл JSON, который используется для создания интерфейса Tkinter через pytkgen. В этом JSON-файле есть определения для нескольких кнопок, каждому из которых дано уникальное имя. При назначении команд этим кнопкам им предоставляется одинаковый обратный вызов, но обратный вызов должен знать, какая кнопка инициировала вызов, и вы хотите сделать это через имя. Это верно?

Если да, то я предполагаю, что вы в настоящее время создания обратного вызова назначения, как это (очень общий пример, предполагая, что root является корневой интерфейс, возвращаемый вызовом tkgen.gengui.TkJson с пути к файлу JSON):

root.button("name1", callback) 
root.button("name2", callback) 
... 

Это не дает вам имя, которое вы хотите. Один из способов передать имя - создать lambda, который передает имя кнопки функции обратного вызова. Функция обратного вызова задания будут выглядеть примерно так:

root.button("name1", lambda:callback("name1")) 
root.button("name2", lambda:callback("name2")) 
... 

Тогда ваше определение обратного вызова может выглядеть следующим образом:

def callback(name): 
    if name == "name1": 
     # Do something in here 
    elif name == "name2": 
     # Do something else in here 
    ... 

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

def cb_button(i): 
    print i 

buttons = [('btn'+str(i), i) for i in range(10)] 
for (b, i) in buttons: 
    root.button(b, lambda x=i: cb_button(x)) 
+0

Я бы написал 'root.button (" name1 ", lambda: callback (" name1 "))' – FabienAndre

+0

@FabienAndre: Хорошая точка. Я думаю, что я думал о другом сценарии, когда требуемые данные должны передаваться через аргумент ключевого слова (т. Е. Если кнопки генерируются циклом, используя переменную цикла в качестве данных для передачи обратного вызова). Я обновил свой пример. –

+0

Хорошая идея, +1, но, пожалуйста, посмотрите мою проблему в вопросе. –

0

я не могу вспомнить, как получить имя, но вы всегда можете перечислить все, что с помощью

печати реж (событие)

или

печати реж (event.widget)

+0

thx, для этого я просто нажимаю вкладку на ipython, но их слишком много, и никто из них, выглядевший многообещающим, был полезен. –

0

commmon способ заключается в использовании общей функции, но не точно такой же обратный вызов (через закрытие лямбды, как указано на Justin's answer).

Есть два несовершенных альтернатив, опирающихся на внутренностях инструментариев:

  • Tkinter обеспечивает частный атрибут _name в виджете
  • pytkgen корневой особенность widgets dictionnary можно перебирать, чтобы найти назад ваши имена виджетов (name = [k for k, v in root.widgets.iteritems() if v == event.widget][0]) , Для лучшего разделения кода, вы можете извлечь корень из виджета с event.widget._nametowidget('.')

Стоит отметить, эти решения не будут работать с кнопкой command, которая не обеспечивает событие их обратный вызов. И привязка к кнопкам предпочтительнее выполняется с помощью command, поскольку он реализует обычное поведение кнопки (действие при выпуске, вы можете прервать, оставив кнопку ...).