2012-08-10 3 views
4

Tkinter 콜백으로 실행되는 함수에서 반환 된 객체 (또는 변수 등은 모두 기본적으로 같지만 그렇지 않습니다.)를 어떻게 얻을 수 있습니까?Python - Tkinter 콜백에서 돌아 가기

import Tkinter as Tk 
from functools import partial 

def square(x): 
    return x*x 

root = Tk.Tk() 
var = Tk.IntVar(root, value=0) #the variable the gets passed to the class call 
menu = Tk.OptionMenu(root, var, *[0,1,2,3,4,5]) #a drop-down list to choose a value for the variable 
menu.pack() 
button = Tk.Button(root, text='click', command = partial(square,var.get())) #a button that calls the class 
button.pack() 
root.mainloop() 

명백히 간단한 예입니다. 실제로 버튼에 의해 호출 된 함수는 객체를 반환 할 것이고, 추가 작업을 위해 기본 파이썬 네임 스페이스에 보관 될 객체 목록에 추가하고 싶습니다.

어쨌든 여기에서 사용자는 GUI를 사용하여 함수에 대한 인수를 선택하고 함수를 실행할 단추를 누를 수 있습니다. 그러나 함수의 반환 값은 콜백이 반환을 허용하지 않으므로 오더에 손실 될 것으로 보입니다. 이것은 square(x)의 정의에서 추악한 global을 사용하지 않고 극복 할 수 있습니까?

+0

실제로 'partial'내부의'var.get()'에 대한 호출이 실제로 작동하지 않을 수도 있습니다. 버튼을 클릭했을 때가 아니라 버튼을 만들 때 평가되기 때문입니다. 이 구름이 문제가되게하지 마라. 나의 질문은 정말로 'square (x)'에서 버튼으로 되돌아가는 것에 관한 질문이다. –

+1

'partial'에 대한 호출을'lambda' 함수로 바꾸면됩니다 :'command = lambda x = var.get() : square (x)'. var.trace()를 설정할 수도있다. –

답변

8

콜백에서 값을 "반환"한다는 개념은 이벤트 기반 프로그램의 컨텍스트에서 의미가 없습니다. 콜백은 이벤트의 결과로 호출되므로 값을 반환 할 곳이 없습니다.

일반적으로, 콜백은 functools.partial 또는 lambda을 사용하는 대신 항상 함수를 호출해야합니다. 이 두 가지는 필요에 따라 적절하지만 객체 지향 스타일의 코딩 스타일을 사용하는 경우 불필요한 경우가 많으며 필요 이상으로 유지 관리하기 어려운 코드로 이어질 수 있습니다.

예를 들어

:

def compute(): 
    value = var.get() 
    result = square(value) 
    list_of_results.append(result) 

button = Tk.Button(root, text='click', command = compute) 
... 

이 훨씬 쉽게되고, 당신은 클래스와 응용 프로그램 만들 경우, 전역 변수를 방지 할 수 있습니다 : 육년 지각에 대한

class App(...): 
    ... 
    def compute(): 
     ... 
     result = self.square(self.var.get()) 
     self.results.append(result) 
+0

첫 번째 예제의'list_of_results.append()'줄은 약간 짜증을냅니다. 명시 적으로 전역 변수라고 부르는지 여부에 관계없이 해당 범위를 벗어나는 변수를 수정하는 기능이 이상하게 느껴집니다. 전체 프로그램을 수업으로 구현하는 것은 좋은 생각입니다. –

+0

@poorsod : 로컬 범위 외부의 변수를 변경하는 것 외에는 선택의 여지가 없습니다. 그것이 GUI의 작동 방식입니다. 앞에서 말했듯이 콜백은 호출자가 없어 (이벤트 루프가 아닌) 호출자에게 값을 반환 할 수 없습니다. 그러나 콜백이 "응용 프로그램 개체의 범위 내에서"발생한다고 생각하면보다 의미가 있습니다. 콜백은 단순히 자체 객체의 속성을 변경하는 것입니다. –

0

버튼으로 호출되는 실제 함수를 만들면 모든 인라인 대신 그 함수를 만들 수 있습니다.

def someFxn(): your code

button=Tk.Button(parent, text='click', command=someFxn)

다음 함수는 단지의 var.get()를 호출하여 계산을 수행 한 후 값으로 뭔가를 할에.

1

미안하지만, 최근에 나는 코드를 지저분하고 유지하기 어렵게하지 않고 이것을 수행하는 좋은 방법을 알아 냈습니다. 이것은 거의 DaveTheScientist이 말한 것입니다.하지만 저는 조금 더 확장하려고합니다. 버튼을 누를 때마다

exampleButton = Button(root, text = 'Example', command = someFunc) 

이 단순히 someFunc를 호출합니다 : 당신이 갖고 싶어 보통은 Tkinter에서, 버튼이 다음을 수행하는 함수를 호출합니다. 이 기능은, 그러나, 인수를 취하면이 같은 것을 람다를 사용하여 수행해야합니다 코드의

exampleButton = Button(root, text = 'Example', command = lambda: someFunc(arg1, arg2)) 

위의 라인은 someFunc을 실행하고 그 함수의 인수로 변수 arg1arg2을 사용합니다. 자, 버튼을 사용하여 값을 반환하는 함수가 필요할 때가 많은 버튼에서 호출되는 새로운 함수를 만드는 것은 프로그램에서 무엇을 할 수 있었는지를 보여줍니다.

이 함수는 버튼을 첫 번째 인수로 실행하고 그 함수의 인수를 나중에 가져 오는 함수를 사용합니다. 버튼을 만들 때

def buttonpress(function, *args): 
    value = function(*args) 

그런 다음, 당신이 할 :

exampleButton = Button(root, text = 'Example', command = lambda: buttonpress(someFunc, arg1, arg2)) 

이 (이 경우, someFunc) 지정된 기능을 실행하고 value 변수에 반환 값을 저장합니다. 또한 단추가 실행되는 함수에 대해 원하는만큼의 인수를 사용할 수 있다는 이점이 있습니다.