Еще одна «несоответствующая» проблема, которую я обнаружил, когда-то мне удалось получить две копии класса по какой-то причине.
Я добавлял ключи к неправильной копии. Интерфейс Builder все еще видел ключи и позволял мне подключаться к ним, но во время выполнения он использовал другую копию класса, у которой не было новых ключей.
Чтобы найти, какая была «правильная» копия, я использовал cmd-click XCode для имени класса в другом месте, чтобы перейти к правильной копии, затем я удалил плохие неиспользуемые копии (после внесения моих изменений из неиспользуемая копия).
Мораль истории: файлы с дублирующимися файлами плохие.
Я лично предпочитаю использовать lambdas
в таком сценарии, потому что imo он более ясный и простой, а также не заставляет вас писать много методов-оболочек, если у вас нет контроля над вызываемым методом, но это, безусловно, вопрос о вкусе.
Вот как вы это сделаете с помощью лямбда (обратите внимание, что в функциональном модуле также реализована реализация карри, поэтому вы также можете использовать это):
button = Tk.Button(master=frame, text='press', command= lambda: action(someNumber))
Причина, по которой он немедленно вызывает метод, и нажатие кнопки ничего не значит, что action(somenumber)
оценивается, а его возвращаемое значение присваивается как команда для кнопки. Поэтому, если action
печатает что-то, чтобы сообщить вам, что он запустил и возвращает None
, вы просто запустите action
, чтобы оценить его возвращаемое значение, и задали None
как команду для кнопки.
To есть кнопки для вызова функций с разными аргументами, вы можете использовать глобальные переменные, хотя я не могу это рекомендовать:
import Tkinter as Tk
frame = Tk.Frame(width=5, height=2, bd=1, relief=Tk.SUNKEN)
frame.grid(row=2,column=2)
frame.pack(fill=Tk.X, padx=5, pady=5)
def action():
global output
global variable
output.insert(Tk.END,variable.get())
button = Tk.Button(master=frame, text='press', command=action)
button.pack()
variable = Tk.Entry(master=frame)
variable.pack()
output = Tk.Text(master=frame)
output.pack()
if __name__ == '__main__':
Tk.mainloop()
Я бы сделал, чтобы сделать class
, объекты которого будут содержать всю требуемую переменную и методы их изменения по мере необходимости:
import Tkinter as Tk
class Window:
def __init__(self):
self.frame = Tk.Frame(width=5, height=2, bd=1, relief=Tk.SUNKEN)
self.frame.grid(row=2,column=2)
self.frame.pack(fill=Tk.X, padx=5, pady=5)
self.button = Tk.Button(master=self.frame, text='press', command=self.action)
self.button.pack()
self.variable = Tk.Entry(master=self.frame)
self.variable.pack()
self.output = Tk.Text(master=self.frame)
self.output.pack()
def action(self):
self.output.insert(Tk.END,self.variable.get())
if __name__ == '__main__':
window = Window()
Tk.mainloop()
На основе ответа Мэтта Томпсона: класс можно сделать вызываемым, чтобы он мог использоваться вместо функции:
import tkinter as tk
class Callback:
def __init__(self, func, *args, **kwargs):
self.func = func
self.args = args
self.kwargs = kwargs
def __call__(self):
self.func(*self.args, **self.kwargs)
def default_callback(t):
print("Button '{}' pressed.".format(t))
root = tk.Tk()
buttons = ["A", "B", "C"]
for i, b in enumerate(buttons):
tk.Button(root, text=b, command=Callback(default_callback, b)).grid(row=i, column=0)
tk.mainloop()
JasonPy - несколько вещей ...
, если вы нажмете кнопку в цикле, она будет создаваться снова и снова ... что, вероятно, не то, что вы хотите. (возможно, это так) ...
Причина, по которой он всегда получает последний индекс, - это события lambda, выполняемые при нажатии на них, а не при запуске программы. Я не уверен на 100%, что вы делаете, но, возможно, попытайтесь сохранить значение, когда оно будет сделано, а затем позвоните позже с помощью кнопки лямбда.
например: (не используйте этот код, просто пример)
for entry in stuff_that_is_happening:
value_store[entry] = stuff_that_is_happening
, тогда вы можете сказать ....
button... command: lambda: value_store[1]
надеюсь это помогает!
Это также можно сделать, используя partial
из стандартной библиотеки functools , например:
from functools import partial
#(...)
action_with_arg = partial(action, arg)
button = Tk.Button(master=frame, text='press', command=action_with_arg)
button = Tk.Button(master=frame, text='press', command=partial(action, arg))
– Klamer Schutte
18 February 2015 в 23:11
button = Tk.Button(master=frame, text='press', command=lambda: action(someNumber))
Я считаю, что это исправить
Используйте lambda для передачи данных входа в командную функцию, если у вас есть больше действий для выполнения, например (я попытался сделать ее общей, поэтому просто адаптирую):
event1 = Entry(master)
button1 = Button(master, text="OK", command=lambda: test_event(event1.get()))
def test_event(event_text):
if not event_text:
print("Nothing entered")
else:
print(str(event_text))
# do stuff
Это передаст информацию в случае функции кнопки. Там может быть больше питонских способов написания этого, но это работает для меня.
Способность Python предоставлять значения по умолчанию для аргументов функции дает нам выход.
def fce(x=myX, y=myY):
myFunction(x,y)
button = Tk.Button(mainWin, text='press', command=fce)
См.: http://infohost.nmt.edu/tcc/help/pubs/tkinter /web/extra-args.html
Для большего количества кнопок вы можете создать функцию, которая возвращает функцию:
def fce(myX, myY):
def wrapper(x=myX, y=myY):
pass
pass
pass
return x+y
return wrapper
button1 = Tk.Button(mainWin, text='press 1', command=fce(1,2))
button2 = Tk.Button(mainWin, text='press 2', command=fce(3,4))
button3 = Tk.Button(mainWin, text='press 3', command=fce(9,8))
myX
и myY
, отлично работает.
– Tadhg McDonald-Jensen
25 February 2016 в 20:51
Для потомков: вы также можете использовать классы для достижения чего-то подобного. Например:
class Function_Wrapper():
def __init__(self, x, y, z):
self.x, self.y, self.z = x, y, z
def func(self):
return self.x + self.y + self.z # execute function
Кнопка может быть просто создана:
instance1 = Function_Wrapper(x, y, z)
button1 = Button(master, text = "press", command = instance1.func)
Этот подход также позволяет вам изменять аргументы функции, например, instance1.x = 3
.
Один простой способ - настроить button
на lambda
следующим образом:
button['command'] = lambda arg1 = local_var1, arg2 = local_var2 : function(arg1, arg2)
partial
, работает в этом случае. – Scrontch 18 July 2014 в 14:46callback=lambda x=x: f(x)
, как вfs = [lambda x=x: x*2 for x in range(5)] ; print [f() for f in fs]
– gboffi 10 November 2014 в 01:34