0

カスタムウィジェットにマウススクロールイベントを受信させる方法を分類できません。ルートウィンドウにバインドすると、通知が発生します。また、ウィジェット(ここでは単純なリストボックス)以外のルートウィンドウの子にバインドすると、通知も発生します(ホイールを動かしたときにリストが動くのを見るとわかります)。私は何を見落としていますか?

roll()が呼び出されないサンプルコード:

#!/usr/bin/python3
from tkinter import *
from tkinter.ttk import *

class CustomWidget(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.width = 200
        self.height = 200
        self.canvas = Canvas(self, width=200, height=200)
        self.canvas.config(background='red')
        self.canvas.pack()

        self.bind('<MouseWheel>', self.roll)
        self.bind('<Button-4>', self.roll)
        self.bind('<Button-5>', self.roll)

    def roll(self, event):
        print("detected mouse roll!");

if __name__ == "__main__":
    root = Tk()
    root.wm_title("TestRoot")

    sb = Scrollbar(root, orient=VERTICAL)
    lb = Listbox(root, yscrollcommand=sb.set)
    sb.config(command=lb.yview)
    cw = CustomWidget(root)

    for char in list("abcdefghijklmnopqrstuvwxyz"):
        lb.insert(END, char)

    cw.pack()
    lb.pack()
    sb.pack()

    root.update()
    root.mainloop()
4

1 に答える 1

1

したがって、フレームがイベントを受信するには、フォーカスが必要です。それを呼び出すことはできますframe.set_focus()が、別のウィジェットにフォーカスを与えるとすぐに機能しなくなります。これを回避するには、フレームにバインドしてフォーカスをフレームに設定しますが、キャンバスはフレームのサイズ全体を占めるため、代わりにイベントをそれに<Button-1>バインドする必要があります。<Button-1>

追加:

self.canvas.bind("<Button-1>", lambda _: self.focus_set())

他のバインディングをCustomWidget.__init__入力すると、ウィジェットにフォーカスがある限りバインディングが機能します。これは、ユーザーがウィジェットをクリックしたときに機能します(リストボックスの動作と同様です)。キャンバスがフレームほど大きくならない場合は、<Button-1>フレームに別のバインディングを追加する必要があります。

于 2012-07-19T15:46:24.110 に答える