Ubuntu环境下Tkinter Frame如何绑定鼠标滚轮触发滚动
问题根源
两个问题导致功能异常:
- 原代码存在Tkinter语法错误:把控件创建和
pack()布局方法链式调用后赋值给变量,布局方法返回值固定为None,会导致后续对画布、滚动条的配置操作全部失效。 - Ubuntu属于Linux发行版,Tkinter在Linux下的鼠标滚轮事件逻辑和Windows不同:不响应
<MouseWheel>事件,滚轮上下滚动会分别触发独立的鼠标按键事件:- 滚轮向上:触发
<Button-4>事件 - 滚轮向下:触发
<Button-5>事件
- 滚轮向上:触发
修复方案
- 拆分所有控件的创建和布局代码,不要链式调用pack/grid/place后赋值给控件变量
- 编写滚轮滚动处理函数,调用画布的
yview_scroll()方法实现纵向滚动 - 给画布、内部容器帧、所有子控件都绑定滚轮事件,避免鼠标悬停在内部控件上时事件被抢占导致滚轮失效
修复后可直接运行的代码
from tkinter import * from tkinter import ttk win = Tk() wrapper1 = LabelFrame(win) # 拆分画布创建和布局逻辑 mycanvas = Canvas(wrapper1) mycanvas.pack(side=LEFT, fill='both', expand='yes') # 拆分滚动条创建和布局逻辑 yscrollbar = ttk.Scrollbar(wrapper1, orient="vertical", command=mycanvas.yview) yscrollbar.pack(side=RIGHT, fill='y') mycanvas.configure(yscrollcommand=yscrollbar.set) mycanvas.bind('<Configure>', lambda e: mycanvas.configure(scrollregion = mycanvas.bbox('all'))) myframe = Frame(mycanvas) mycanvas.create_window((0,0), window=myframe, anchor='nw') # 滚轮滚动处理函数,步长可自行调整,数值越大滚动速度越快 def handle_mousewheel(event): scroll_step = 3 if event.num == 4: mycanvas.yview_scroll(-scroll_step, "units") elif event.num == 5: mycanvas.yview_scroll(scroll_step, "units") # 给画布、内部帧绑定滚轮事件 mycanvas.bind("<Button-4>", handle_mousewheel) mycanvas.bind("<Button-5>", handle_mousewheel) myframe.bind("<Button-4>", handle_mousewheel) myframe.bind("<Button-5>", handle_mousewheel) wrapper1.pack(fill="both", expand="yes", padx=10, pady=10) for i in range(30): btn = Button(myframe, text="btn" + str(i)) btn.pack() # 给所有子按钮绑定滚轮事件,避免悬停在按钮上时滚轮无响应 btn.bind("<Button-4>", handle_mousewheel) btn.bind("<Button-5>", handle_mousewheel) win.geometry("500x500") win.resizable(height=FALSE,width=FALSE) win.mainloop()
补充说明
如果需要做跨平台兼容,可以在绑定事件前判断当前运行平台:
- Windows/macOS平台绑定
<MouseWheel>事件,通过event.delta计算滚动方向和步长 - Ubuntu等Linux平台绑定上述
<Button-4>、<Button-5>事件即可
内容的提问来源于stack exchange,提问作者Zahid Hossen
相关产品推荐
相关产品推荐

