如何将guizero控件添加到tkinter Canvas实现可滚动区域
guizero Canvas 可滚动容器实现方案
核心实现逻辑
guizero控件本质是tkinter控件的上层封装,无法直接作为Canvas的绘制元素嵌入。要实现类似Box的可控容器+滚动效果,需要先在Canvas内部嵌入一个原生tkinter Frame作为内容宿主,再将guizero控件挂载到这个Frame上,最后绑定滚动规则即可。
关键实现步骤
- 不要直接将guizero控件的master属性设为Canvas实例,否则控件会悬浮在Canvas上层,无法跟随滚动、也无法参与Canvas的布局计算
- 调用Canvas的
create_window()方法创建内嵌Frame,作为滚动区域的内容容器 - 给内嵌Frame绑定
<Configure>事件,当内部内容尺寸变化时,自动更新Canvas的scrollregion属性,保证滚动范围覆盖所有内容 - 按需为Canvas添加垂直/水平滚动条,绑定滚动动作,可选添加鼠标滚轮支持
- 将内嵌Frame包装为guizero可识别的Box对象,后续就可以像操作普通guizero Box一样,在这个容器内添加、布局、修改控件
修正后的可运行代码
import tkinter as tk from guizero import * from PIL import Image def file_function(): print("File option") def edit_function(): print("Edit option") def open_png(): global level_img path = filedialog.askopenfilename(title='choose image', defaultextension="*.png", filetypes=(('png image', '*.png'),('any file', '*.*'))) print(path) if path == '': return level_img = Image.open(path) picture.image = level_img # 初始化主窗口 app = App(title="Hello world", layout='grid') menubar = MenuBar(app, toplevel=["File", "Edit"], options=[ [ ["open png", open_png], ['open with selector', file_function], ["save", file_function], ['export xml', file_function], ['export png', file_function] ], [ ["Edit option 1", edit_function], ["Edit option 2", edit_function] ] ]) # 创建带滚动条的Canvas容器 # 垂直滚动条 v_scroll = ScrollBar(app, grid=[1,0], vertical=True) objects = tk.Canvas(app.tk, highlightthickness=5, highlightbackground='black', yscrollcommand=v_scroll.set) v_scroll.config(command=objects.yview) # 创建Canvas内部的宿主Frame inner_frame = tk.Frame(objects) # 将Frame嵌入Canvas objects.create_window((0,0), window=inner_frame, anchor='nw') # 将原生tk Frame包装为guizero Box,后续所有滚动区域内的控件都挂载到这个Box上 scroll_box = Box(inner_frame, layout='grid') # 自动更新滚动范围 def update_scrollregion(event): objects.configure(scrollregion=objects.bbox("all")) inner_frame.bind("<Configure>", update_scrollregion) # 绑定鼠标滚轮滚动 def on_mousewheel(event): objects.yview_scroll(int(-1*(event.delta/120)), "units") objects.bind_all("<MouseWheel>", on_mousewheel) # 加载初始图片 img = tk.PhotoImage(file="image.png") objects.create_image(0,0, image=img, anchor='nw') # 测试控件:全部挂载到scroll_box,和普通Box用法完全一致 text = Text(scroll_box, text='this is a test', grid=[0,0]) picture = Picture(scroll_box, grid=[0,1]) # 可以随意加更多控件测试滚动效果 for i in range(20): PushButton(scroll_box, text=f"测试按钮{i}", grid=[0, 2+i], command=file_function) # 将Canvas添加到主窗口 app.add_tk_widget(objects, grid=[0,0], width=200, height=300) app.display()
使用说明
后续开发时,所有需要放在滚动区域内的guizero控件,只需将父容器指定为代码中的
scroll_box即可,支持grid/auto布局、动态增删控件、属性修改,当内容总高度/宽度超出Canvas设定的200*300尺寸时,会自动出现滚动条,支持拖动滚动条和鼠标滚轮滚动。
内容的提问来源于stack exchange,提问作者ego-lay atman-bay
相关产品推荐
相关产品推荐

