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 回答