Button 매개 변수 "command"가 선언 될 때 실행되는 이유는 무엇입니까?
내 코드는 다음과 같습니다.
from Tkinter import *
admin = Tk()
def button(an):
print an
print 'het'
b = Button(admin, text='as', command=button('hey'))
b.pack()
mainloop()
버튼이 작동하지 않고 내 명령없이 'hey'와 'het'을 한 번 인쇄 한 다음 버튼을 눌러도 아무 일도 일어나지 않습니다.
이 코드를 고려하십시오.
b = Button(admin, text='as', command=button('hey'))
다음과 정확히 동일합니다.
result = button('hey')
b = button(admin, text='as', command=result)
이 command
옵션은 함수에 대한 참조를 가져 오므로 함수 이름을 전달해야한다는 멋진 방법입니다. 참조를 전달하려면 괄호 나 인수를 사용하지 않고 이름 만 사용해야합니다. 예를 들면 :
b = Button(... command = button)
"hey"와 같은 매개 변수를 전달하려면 약간의 추가 코드를 사용해야합니다.
- 인수없이 호출 할 수있는 중간 함수를 만든 다음
button
함수 를 호출 할 수 있습니다. - 를 사용
lambda
하여 익명 함수 라고 하는 것을 만들 수 있습니다 . 모든면에서 이름이없는 것을 제외하고는 함수입니다.lambda
명령 을 호출하면 생성 된 함수에 대한 참조 가 반환 됩니다command
. 즉, 버튼 에 대한 옵션 값으로 사용할 수 있습니다 . - functools.partial 을 사용할 수 있습니다.
나를 위해, 어떤 사람들은 이해하기 더 쉽다고 생각하지만 lambda
추가 수입이 필요하지 않기 때문에 가장 간단합니다 .functools.partial
functools.partial
button
인수로 함수를 호출하는 람다 함수를 만들려면 다음과 같이하면됩니다.
lambda: button('hey')
기능적으로 다음과 같은 함수로 끝납니다.
def some_name():
button('hey')
앞서 말했듯이, lambda
이 이름없는 함수에 대한 참조를 반환합니다. 참조는 command
옵션에서 기대 하는 것이므로 lambda
버튼을 만들 때 직접 사용할 수 있습니다 .
b = Button(... command = lambda: button('hey'))
이 사이트에는 일반적으로 람다에 대한 흥미로운 의견이 많이있는 질문이 있습니다. Python 람다가 유용한 이유 질문을 참조하세요 . . 동일한 토론에는 콜백에 변수를 전달해야 할 때 루프에서 람다를 사용하는 방법을 보여주는 답변이 있습니다.
마지막으로 effbot.org의 Tkinter 콜백 섹션 에서 멋진 자습서를 참조하십시오. 람다의 범위는 매우 적지 만 정보는 여전히 유용 할 수 있습니다.
명령으로 사용할 수있는 매개 변수없이 함수를 생성해야합니다.
b = Button(admin, text='as', command=lambda: button('hey'))
이 문서의 "콜백에 인수 전달"섹션을 참조하십시오 .
GUI 예 :
GUI가 있다고 가정 해 보겠습니다.
import tkinter as tk
root = tk.Tk()
btn = tk.Button(root, text="Press")
btn.pack()
root.mainloop()
버튼을 눌렀을 때 일어나는 일
를 btn
누르면 다음 예제 와 매우 유사한 자체 함수가 호출됩니다 button_press_handle
.
def button_press_handle(callback=None):
if callback:
callback() # Where exactly the method assigned to btn['command'] is being callled
와:
button_press_handle(btn['command'])
당신은 단순히 생각할 수있는 command
옵션으로 설정해야 우리가 원하는 방법에 대한 참조가 유사하게 호출 할 callback
에서 button_press_handle
.
버튼을 눌렀을 때 메서드 호출 ( Callback )
인수 없이
따라서 print
버튼을 눌렀을 때 무언가를 원하면 다음을 설정해야합니다.
btn['command'] = print # default to print is new line
에주의를 기울이 부족 의 ()
에 print
있음을 의미 생략 방법 : "이것은 내가 누르면 통화 할 메서드의 이름입니다 만 . 단지 바로이 순간을 호출하지 않습니다" 그러나에 대한 인수를 전달하지 않았으므로 인수 print
없이 호출 될 때 인쇄되는 모든 것을 인쇄했습니다.
와 인수 (들)
이제 버튼을 눌렀을 때 호출하려는 메서드에 인수를 전달 하려면 람다 문 으로 생성 할 수있는 익명 함수를 사용할 수 있습니다 .이 경우 print
에는 다음과 같이 내장 메서드에 대해 생성 할 수 있습니다. :
btn['command'] = lambda arg1="Hello", arg2=" ", arg3="World!" : print(arg1 + arg2 + arg3)
버튼을 눌렀을 때 여러 메서드 호출
인수 없이
using lambda
문을 달성 할 수도 있지만 나쁜 습관으로 간주되므로 여기에 포함하지 않겠습니다. 좋은 방법은 multiple_methods
원하는 메서드를 호출 한 다음 버튼 누름에 대한 콜백으로 설정 하는 별도의 메서드를 정의하는 것입니다.
def multiple_methods():
print("Vicariously") # the first inner callback
print("I") # another inner callback
와 인수 (들)
다른 메서드를 호출하는 메서드에 인수를 전달하려면 다시 lambda
문 을 사용하십시오 .
def multiple_methods(*args, **kwargs):
print(args[0]) # the first inner callback
print(kwargs['opt1']) # another inner callback
다음을 설정하십시오.
btn['command'] = lambda arg="live", kw="as the" : a_new_method(arg, opt1=kw)
콜백에서 객체 반환
또한 더 참고 callback
할 수없는 정말 return
이 단지 내부라고 때문 button_press_handle
으로 callback()
반대 return callback()
. 그것은 않습니다 return
만 하지 아무 곳이나 그 함수 외부. 따라서 현재 범위에서 액세스 할 수있는 개체를 수정 해야합니다 .
전역 개체 수정이 포함 된 전체 예제
아래 예제는 btn
버튼을 누를 때마다의 텍스트 를 변경하는 메서드를 호출합니다 .
import tkinter as tk
i = 0
def text_mod():
global i, btn # btn can be omitted but not sure if should be
txt = ("Vicariously", "I", "live", "as", "the", "whole", "world", "dies")
btn['text'] = txt[i] # the global object that is modified
i = (i + 1) % len(txt) # another global object that gets modified
root = tk.Tk()
btn = tk.Button(root, text="My Button")
btn['command'] = text_mod
btn.pack(fill='both', expand=True)
root.mainloop()
엔진은 "... command = ..."줄에 값을 할당 할 때 함수의 결과를 평가합니다.
"명령"은 함수가 반환 될 것으로 예상하기 때문에 람다를 사용하면 평가 중에 "명령"으로 반환되는 Anomymous 함수가 생성되므로 작업을 수행 할 수 있습니다. 자신 만의 함수를 코딩 할 수도 있습니다. 또한 작업을 수행합니다.
이것은 람다가 있고 람다가없는 예입니다.
#!/usr/bin/python
# coding=utf-8
from Tkinter import *
# Creation de la fenêtre principale (main window)
Mafenetre = Tk()
res1 = StringVar()
res2 = StringVar()
def isValidInput(obj):
if hasattr(obj, 'get') and callable(getattr(obj, 'get')):
return TRUE
return FALSE
# stupid action 2 (return 12 on purpose to show potential mistake)
def action1(*arguments):
print "action1 running"
for arg in arguments:
if isValidInput(arg):
print "input value: ", arg.get()
res1.set(arg.get())
else:
print "other value:", arg
print "\n"
return 12
# stupid action 2
def action2(*arguments):
print "action2 running"
a = arguments[0]
b = arguments[1]
if isValidInput(a) and isValidInput(b):
c = a.get() + b.get()
res2.set(c)
print c
print "\n"
# a stupid workflow manager ordered by name
def start_tasks(*arguments, **keywords):
keys = sorted(keywords.keys())
for kw in keys:
print kw, "plugged "
keywords[kw](*arguments)
# valid callback wrapper with lambda
def action1_callback(my_input):
return lambda args=[my_input]: action1(*args)
# valid callback wrapper without lambda
def action1_callback_nolambda(*args, **kw):
def anon():
action1(*args)
return anon
# first input string
input1 = StringVar()
input1.set("delete me...")
f1 = Entry(Mafenetre, textvariable=input1, bg='bisque', fg='maroon')
f1.focus_set()
f1.pack(fill="both", expand="yes", padx="5", pady=5)
# failed callback because the action1 function is evaluated, it will return 12.
# in this case the button won't work at all, because the assignement expect a function
# in order to have the button command to execute something
ba1 = Button(Mafenetre)
ba1['text'] = "show input 1 (ko)"
ba1['command'] = action1(input1)
ba1.pack(fill="both", expand="yes", padx="5", pady=5)
# working button using a wrapper
ba3 = Button(Mafenetre)
ba3['text'] = "show input 1 (ok)"
# without a lambda it is also working if the assignment is a function
#ba1['command'] = action1_callback_nolambda(input1)
ba3['command'] = action1_callback(input1)
ba3.pack(fill="both", expand="yes", padx="5", pady=5)
# display result label
Label1 = Label(Mafenetre, text="Action 1 result:")
Label1.pack(fill="both", expand="yes", padx="5", pady=5)
# display result value
resl1 = Label(Mafenetre, textvariable=res1)
resl1.pack(fill="both", expand="yes", padx="5", pady=5)
# second input string
input2 = StringVar()
f2 = Entry(Mafenetre, textvariable=input2, bg='bisque', fg='maroon')
f2.focus_set()
f2.pack(fill="both", expand="yes", padx="5", pady=5)
# third test without wrapper, but making sure that several arguments are well handled by a lambda function
ba2 = Button(Mafenetre)
ba2['text'] = "execute action 2"
ba2['command'] = lambda args=[input1, input2], action=action2: start_tasks(*args, do=action)
ba2.pack(fill="both", expand="yes", padx="5", pady=5)
# display result label
Label2 = Label(Mafenetre, text="Action 2 result:")
Label2.pack(fill="both", expand="yes", padx="5", pady=5)
# display result value
resl2 = Label(Mafenetre, textvariable=res2)
resl2.pack(fill="both", expand="yes", padx="5", pady=5)
Mafenetre.mainloop()
함수의 입력이나 괄호로 키워드 나 인수를 사용하지 마십시오. 그것은 매우 쉬운 해결책입니다.
button('hey')
콜백으로 설정하지 않고 함수를 호출합니다.
이것은 내 해결책입니다.
from tkinter import *
admin = Tk()
def button(an):
print(an)
print("het")
def param():
button("hey")
button1 = Button(admin, text = "press", command = param)
button1.pack()
기본적으로 우리가하는 일은 매개 변수로 함수를 정의한 다음 매개 변수없이 함수 내에서 호출하는 것입니다.
참고 URL : https://stackoverflow.com/questions/5767228/why-is-button-parameter-command-executed-when-declared
'Program Tip' 카테고리의 다른 글
Python : 객체가 시퀀스인지 확인 (0) | 2020.12.12 |
---|---|
텍스트 하이라이트 이벤트? (0) | 2020.12.12 |
자식 div를 부모 너비에 맞추는 크로스 브라우저 방법 (0) | 2020.12.12 |
고정 위치 컨테이너에서 콘텐츠 일부 스크롤 (0) | 2020.12.12 |
RestSharp-SSL 오류 무시 (0) | 2020.12.12 |