2012-08-10 118 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() 

顯然這是一個簡化的例子。實際上,按鈕所調用的函數將返回對象,我希望將它們附加到主要Python名稱空間中的對象列表中,以供進一步操作。

總之,這裏的用戶可以選擇使用GUI功能的參數,按下一個按鈕,將執行該功能。然而,函數的返回值似乎註定會失去以太,因爲回調不會接受回報。可以這樣沒有在square(x)定義中使用一個醜陋的global克服?

+0

其實,我認爲()'內'partial'可能不實際工作,因爲在創建按鈕時,它會進行評估,而不是當它被點擊調用'var.get。不過,不要讓這個問題變成這個問題 - 我的問題實際上是從'square(x)'到按鈕的返回。 – 2012-08-10 14:36:19

+1

您可以用'lambda'函數替換調用'partial'繞開這個問題:'命令=拉姆達X = var.get()平方(X)'。你也可以設置一個'var.trace()'。 – 2012-08-10 14:57:25

回答

8

的概念「迴歸」,從回調值沒有任何意義的事件驅動程序的情況下。回調被稱爲事件的結果,所以無處可返回值。

作爲一般的經驗法則,您的回調應該始終調用一個函數,而不是使用functools.partiallambda。這兩種方法在需要時都可以使用,但如果您使用的是面向對象的編碼風格,那麼通常是不必要的,導致代碼難以維護。

例如:

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

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

這變得更加容易,並且你能避免全局變量,如果你創建你的應用程序爲一類:用於爲6旬

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

在你的第一個例子中的'list_of_results.append()'行讓我有點嬌氣。感覺怪異的功能來修改其範圍之外的變量,無論是否明確地把它稱爲​​'global'變量。儘管將整個程序作爲一個類來實現是一個不錯的主意。 – 2012-08-10 22:50:25

+0

@poorsod:沒有,但是它改變之外的局部範圍內的變量選擇。 GUI就是這樣工作的。就像我說的,回調函數不能將值返回給調用者,因爲它們沒有調用者(事件循環除外)。但是,當您想到「在應用程序對象的範圍內」發生回調時,它更有意義。回調只是改變它自己的對象的屬性。 – 2012-08-10 23:26:29

0

只需創建,而不是把它所有內嵌像由你的按鈕稱爲實際功能。

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

def someFxn(): your code

然後在你的函數只是調用var.get(),做你的計算,然後做一些與價值。

1

抱歉,最近我想出了一個很好的方法來做到這一點,而不會讓代碼混亂,難以維護。 這是非常說什麼DaveTheScientist,但我只是想在這裏一點點擴大。 通常,在Tkinter的,如果你想有一個按鈕調用一個函數,你執行以下操作:

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

這就叫someFunc只要按下按鈕。如果這個功能,但是,接受參數,你需要使用lambda表達式和做這樣的事情:

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變量返回的值。它還具有如下優點:您可以根據需要爲按鈕運行的功能使用盡可能多的參數。