2012-03-26 18 views
4

私は、単に出力を出力するよりも意味のあるコールバック関数を実装する方法を正確に把握しようとしています。私はかなり経験が不十分なので、コールバック関数をPython(あるいは他の言語でもどうやって実装すべきか、または実装できるかはわかりません)。Tkinterトレースに関連するコールバック関数の制限はありますか?

は、次のPythonコードを考えてみましょう:

from Tkinter import * 

def callbackfunc(*args): 
    print "Hello World!" 

class App: 

    def __init__(self, master): 
    frame = Frame(master) 
    frame.pack() 

    optionvalue = IntVar(master) 
    optionvalue.set(2) 
    optionvalue.trace("w", callbackfunc) 
    self.optionmenu = OptionMenu(master, optionvalue, 1, 2, 3, 4) 
    self.optionmenu.pack() 

私はより具体的に---その選択した値が変更されたとき、私のコールバック関数は意味のある何かをするようなオプションメニュー(Tkinterのウィジェット)を実装しようとしています、プログラムのどこかで定義されたグローバル変数の値が変更されます。上に実装されているように、それは単に出力を出力します(ただし正常に終了しました)。

コールバック関数にパラメータを渡す方法がわかりません。私はこの特定のコールバック関数が何も返さないようにしたい。しかし、私は自分のコールバック関数が何かを返すようにする方法と、残りのプログラムを実装して、返された結果を利用できるようにする方法について興味があります。実装しようとしていない方法でPythonコールバック関数を実装しようとしていますか?そうでない場合は、どうすればこの問題を解決できますか?

答えて

4

「コールバック関数にパラメータを渡す」ということは、少し不明です。あなたはすでにそれをやっている!たとえば:Tkinterのは、あなたのコールバックを呼び出すとき

from Tkinter import * 

def callbackfunc(*args, **kwargs): 
    print args, kwargs 
    print "Hello World!" 

class App(object): 
    def __init__(self, master): 
     frame = Frame(master) 
     frame.pack() 

     optionvalue = IntVar(master) 
     optionvalue.set(2) 
     optionvalue.trace("w", callbackfunc) 
     self.optionmenu = OptionMenu(master, optionvalue, 1, 2, 3, 4) 
     self.optionmenu.pack() 

root = Tk() 
app = App(root) 
root.mainloop() 

実行...

$ python foo.py 
('PY_VAR0', '', 'w') {} 
Hello World! 

だから、あなたが見る、それにパラメータを渡します。それらを印刷する以外のことをしたいのであれば、関数の代わりにメソッドを渡すことで、それらを何らかの状態で格納することができます。

from Tkinter import * 

class App(object): 
    def __init__(self, master): 
     frame = Frame(master) 
     frame.pack() 

     optionvalue = IntVar(master) 
     optionvalue.set(2) 
     optionvalue.trace("w", self.callbackfunc) 
     self.optionmenu = OptionMenu(master, optionvalue, 1, 2, 3, 4) 
     self.optionmenu.pack() 
     self.state = [] 

    def callbackfunc(self, *args): 
     self.state.append(args) 
     print self.state 


root = Tk() 
app = App(root) 
root.mainloop() 

実行...

$ python foo.py 
[('PY_VAR0', '', 'w')] 
[('PY_VAR0', '', 'w'), ('PY_VAR0', '', 'w')] 
[('PY_VAR0', '', 'w'), ('PY_VAR0', '', 'w'), ('PY_VAR0', '', 'w')] 

はまた、おそらくあなたはoptionvalueの値にアクセスしたいです。あなたはそれへの参照を保存することができます:

​​

実行すると...

$ python foo.py 
[('PY_VAR0', '', 'w')] 
1 
[('PY_VAR0', '', 'w'), ('PY_VAR0', '', 'w')] 
2 
[('PY_VAR0', '', 'w'), ('PY_VAR0', '', 'w'), ('PY_VAR0', '', 'w')] 
3 

noob oddyが示唆するように、あなたはまた、(最初の引数は、コールバックに渡された)name = 'PY_VAR0'root.getvar(name)を使用することができます。

+0

あなたは正しいです、私は完璧な意味を持っていません。私はあなたの最初の例で "** kwargs"で渡したものである "追加の"パラメータを言うつもりでした。しかし、トレース内でパラメータを渡す方法についても混乱しました( "w"を書くと、callbackfunc)。コールバック機能には何も渡せません。 – nairware

+0

@nairwareの場合、コールバック関数に何も渡すことはできません。なぜなら、あなたは関数をコールしていないからです。それはコールバックです。これは、_Tkinter_だけがそれを呼び出すことを意味し、上記のものだけを渡します。 '** kwargs'は「追加パラメータ」ではなく、' * args'のキーワードバージョンです(つまり、位置引数ではなくキーワードを受け入れます)(http://stackoverflow.com/questions/1419046/python-さらに、 '* args'を使用すると、(Tkinterによって)スローされるすべての「追加パラメータ」を受け入れるようになります。 – senderle

+0

@nairware、あなたが何をするか、おそらく何をするかは、関数を返す関数を作成し、その関数にパラメータを渡し、返された関数をコールバックとして渡します。それがしたいことがあれば教えてください。 – senderle

1
from Tkinter import * 

def callbackfunc(name, index, mode): 
    print root.getvar(name) 

class App: 

    def __init__(self, master): 
     frame = Frame(master) 
     frame.pack() 

     optionvalue = IntVar(master) 
     optionvalue.set(2) 
     optionvalue.trace("w", callbackfunc) 
     self.optionmenu = OptionMenu(master, optionvalue, 1, 2, 3, 4) 
     self.optionmenu.pack() 

root = Tk() 
app = App(root) 
root.mainloop() 
2

追加の引数(または選択した引数のみ)を送信する場合は、ラムダを使用できます。ラムダは混乱していると思う人もいますが、強力なツールになることがあります。

しかし、あなたが望むあなたのコールバックを定義します。これらの引数のいずれかあなたとあなたのコールバックを呼び出して、送信したい追加のどんな引数のためのTkinterとキーワード引数で渡された引数を受け入れるように

def callbackfunc(message=None): 
    print message 

利用ラムダを欲しいです。たとえば:

optionvalue.trace("w", lambda name, index, op, 
         message="hello, world": callbackfunc(message)) 

また、間違いなく読みやすい構文で同じことを行うためにfunctools.partialを使用することができます。

関連する問題