[python] Tkinter에서 Button 명령에 인수를 전달하는 방법은 무엇입니까?

Button파이썬에서 Tkinter로 다음을 만들었다 고 가정 해보십시오 .

import Tkinter as Tk
win = Tk.Toplevel()
frame = Tk.Frame(master=win).grid(row=1, column=1)
button = Tk.Button(master=frame, text='press', command=action)

action버튼을 누를 때 메소드 가 호출되지만 메소드에 인수를 전달하려면 어떻게해야 action합니까?

다음 코드로 시도했습니다.

button = Tk.Button(master=frame, text='press', command=action(someNumber))

이것은 단지 메소드를 즉시 호출하고 버튼을 눌러도 아무것도하지 않습니다.



답변

필자는 개인적 lambdas으로 그러한 시나리오에서 사용하는 것을 선호합니다 . 왜냐하면 imo가 더 명확하고 간단하며 호출 된 메소드를 제어 할 수없는 경우 많은 래퍼 메소드를 작성하도록 강요하지는 않지만 맛의 문제입니다.

그것이 람다로하는 방법입니다 (기능 모듈에 카레 구현이 있으므로 사용할 수도 있습니다).

button = Tk.Button(master=frame, text='press', command= lambda: action(someNumber))


답변

다음 과 같이 partial표준 라이브러리 functools 를 사용하여 수행 할 수도 있습니다 .

from functools import partial
#(...)
action_with_arg = partial(action, arg)
button = Tk.Button(master=frame, text='press', command=action_with_arg)


답변

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옵션을 callbackin에서 와 같이 호출하려는 메소드에 대한 참조로 설정해야 한다고 생각할 수 있습니다 button_press_handle.


버튼을 눌렀을 때 메소드 호출 ( 콜백 )

논증 없이

따라서 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)

버튼을 눌렀을 때 여러 메소드 호출

인수 없이

당신은 또한 그 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실제로는 불가능 합니다 . 그것은 않습니다 만 하지 아무 곳이나 그 함수 외부. 따라서 현재 범위에서 액세스 할 수있는 개체를 수정 해야합니다 .returnbutton_press_handlecallback()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()

거울


답변

함수 인수에 기본값을 제공하는 파이썬의 능력은 우리에게 탈출구를 제공합니다.

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))


답변

Matt Thompsons의 답변 : 클래스를 호출 가능하게 만들어 함수 대신 사용할 수 있습니다.

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()


답변

메소드를 즉시 호출하고 버튼을 눌러도 아무것도 수행되지 않는 이유 action(somenumber)는 평가되고 리턴 값이 버튼의 명령으로 간주되기 때문입니다. 따라서 action무언가가 run and returns이라는 것을 인쇄 None하면 action반환 값을 평가하고 주어진None 하고 버튼의 명령으로 됩니다.

다른 인수로 함수를 호출하는 버튼을 사용하려면 전역 변수를 사용할 수 있지만 권장하지는 않습니다.

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()


답변

button = Tk.Button(master=frame, text='press', command=lambda: action(someNumber))

나는 이것을 고쳐야한다고 믿는다.