5

ボタンの範囲に共通のコールバックがあります。コールバックが呼び出されたら、以前に割り当てられた名前で発信者を識別したいと思います。しかし、Tkinter のドキュメントでは、これを行う方法がわかりませんでした。何か案は?

私のプログラムは約です。

def callback(event):
    event.widget['text'] # 'name' does not work so 
                         # I have to use the label of the button now, but it is a dirty solution.

root.bind("<Button-1>", cb_button)

pytkgenを使用して JSON から GUI をロードするため、名前が必要です。

更新:ジャスティンのソリューションは良さそうに見えますが、どのボタンがクリックされたかに関係なく
、次のコードが常に出力されるのはなぜですか?9

def cb_button(i):
    print i

buttons = [('btn'+str(i), i) for i in range(10)]
for (b, i) in buttons:
    root.button(b, lambda: cb_button(i))
4

3 に答える 3

4

ウィジェットの winfo_name() メソッドは、ウィジェットの名前を返します。これは通常、文字列として表される 8 桁の数字です。例: '40123211' イベント オブジェクト evt がある場合は、evt.widget.winfo_name() を使用します。

質問の本文では、別のことを尋ねています。「どのボタンが一般的なコールバック関数を呼び出したかをどのように知ることができますか」

ラムダ関数を使用して、一意の値を共通のコールバックに渡します。

あなたの質問の更新に基づいて、問題を理解していると思います。pytkgen を介して Tkinter インターフェイスを作成するために使用される JSON ファイルがあります。この JSON ファイルには、いくつかのボタンの定義があり、それぞれに一意の名前が付けられています。これらのボタンにコマンドを割り当てるとき、それらにはすべて同じコールバックが与えられますが、コールバックはどのボタンが呼び出しを開始したかを知る必要があり、名前を介してそれを行う必要があります。あれは正しいですか?

もしそうなら、私はあなたが現在次のようなコールバック割り当てを作成していると推測しています (非常に一般的な例で、JSON ファイルへのパスでroot呼び出すことによって返されるインターフェイス ルートであると想定しています):tkgen.gengui.TkJson

root.button("name1", callback)
root.button("name2", callback)
...

ただし、これはあなたが望む名前を付けているわけではありません。lambda名前を渡す 1 つの方法は、ボタン名をコールバック関数に渡すを作成することです。コールバックの割り当ては次のようになります。

root.button("name1", lambda:callback("name1"))
root.button("name2", lambda:callback("name2"))
...

次に、コールバックの定義は次のようになります。

def callback(name):
    if name == "name1":
        # Do something in here
    elif name == "name2":
        # Do something else in here
    ...

更新: ループ内にボタンを作成している場合は、ラムダ定義を変更して、目的のループ変数をキーワードの既定値として保存する必要があります。それ以外の場合、ループ変数の最終値がすべてのボタンに適用されます。

def cb_button(i):
    print i

buttons = [('btn'+str(i), i) for i in range(10)]
for (b, i) in buttons:
    root.button(b, lambda x=i: cb_button(x))

ウィジェット オブジェクトに属性を追加する

もう 1 つの解決策は、コールバック関数で調べることができるボタン ウィジェット オブジェクトに属性を設定することです。(この例では Tkinter を使用しています)

but1 = Tkinter.Button(root, text="Sync", width=10)
but1.bind("<Button-1>", doButton)
but1.myId = "this"

but2 = Tkinter.Button(root, text="Sync", width=10)
but2.bind("<Button-1>", doButton)
but2.myId = "that"
but2.otherStuff = "anything"

def doButton(evt):
  if evt.widget.myId == "this":
    print("This")
  else:
    print("That "+evt.widget.otherStuff)
于 2013-06-06T23:19:09.510 に答える
0

一般的な方法は、一般的な関数を使用することですが、まったく同じコールバックではありません (ジャスティンの回答lambdaで指摘されているように、クロージャーを介して)。

ツールキットの内部に依存する不完全な代替手段が 2 つあります。

  • tkinter_nameはウィジェットにプライベート属性を提供します
  • pytkgen ルート機能には、widgets反復してウィジェット名を見つけることができる辞書があります ( name = [k for k, v in root.widgets.iteritems() if v == event.widget][0])。より良いコード分離のために、ウィジェットからルートを取得できますevent.widget._nametowidget('.')

commandこれらのソリューションは、コールバックにイベントを提供しないボタンでは機能しないことに注意してください。また、ボタンへのアクションのバインド commandは、ボタンの通常の動作を実装するため、優先的に実行されます (リリース時のアクション、ボタンを離れることで中止できます...)。

于 2013-06-07T08:30:17.057 に答える
0

名前を取得する方法を思い出せませんが、を使用していつでもすべてをリストできます

print dir(イベント)

また

print dir(event.widget)

于 2013-06-06T18:15:07.943 に答える