在tkinter中,如何使自定义子窗口小部件接收鼠标滚动事件?

时间:2012-07-18 21:52:28

标签: python user-interface tkinter

我无法理清如何使自定义小部件接收鼠标滚动事件。如果我绑定到根窗口,则会发生通知。如果我绑定到除了我的小部件之外的根窗口的子节点(这里是一个简单的列表框),也会发生通知(通过在移动方向盘时观察列表移动来证明)。我在俯瞰什么?

从不调用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()

1 个答案:

答案 0 :(得分:1)

因此,为了使帧能够接收事件,它需要具有焦点。您可以在其上调用frame.set_focus(),但只要您给予另一个小部件焦点,它就无法工作。为了解决这个问题,我们可以将<Button-1>绑定到框架并将焦点设置到框架上,但是画布会占用框架的整个大小,因此您需要绑定<Button-1>个事件相反。

添加:

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

CustomWidget.__init__中的其他绑定之后,只要窗口小部件具有焦点,就会使绑定工作,当用户单击它时(类似于列表框如何工作)。如果画布永远不会像它的框架一样大,您可能需要在框架上添加另一个<Button-1>绑定。