如何在初始化后通过鼠标拖拽调整tkinter控件的高度或宽度?
问题原因
- 你当前实现的核心问题出在拖拽位移计算和布局参数配置上:
event.y是鼠标相对于分隔符自身的坐标,不是两次鼠标位置的差值,直接用于计算高度会导致尺寸骤变- 上下两个控件都设置了
expand=1,pack布局会自动均分父容器剩余空间,手动修改height属性会被布局逻辑覆盖,无法生效 - 没有做高度边界限制,拖拽到极限位置会出现控件高度为负的异常
修复后的代码
import tkinter as tk from tkinter import ttk from ttkwidgets.autocomplete import AutocompleteEntryListbox # 记录拖拽起始状态的全局变量 drag_start_y = 0 searchbox_start_height = 0 def on_drag_start(event): global drag_start_y, searchbox_start_height # 记录鼠标按下时的Y坐标和searchbox初始高度 drag_start_y = event.y_root searchbox_start_height = searchbox.winfo_height() def resize(event): global drag_start_y, searchbox_start_height # 计算拖拽位移 dy = event.y_root - drag_start_y # 计算新高度,加边界限制避免高度小于20像素 new_search_height = max(20, searchbox_start_height + dy) new_template_height = max(20, frame_navigator.winfo_height() - new_search_height - separator.winfo_height()) # 直接修改控件高度 searchbox.config(height=new_search_height) template.config(height=new_template_height) window = tk.Tk() frame_navigator = tk.Frame(window) frame_navigator.configure(background="white", width=300, height=300) frame_navigator.pack_propagate(0) searchbox = AutocompleteEntryListbox(frame_navigator, completevalues=[], allow_other_values=False) # 移除expand参数,只保留fill适配宽度 searchbox.pack(side=tk.TOP, fill=tk.BOTH) separator = ttk.Separator(frame_navigator, orient='horizontal', cursor="size_ns") # 绑定鼠标按下事件记录起始状态 separator.bind("<ButtonPress-1>", on_drag_start) separator.bind("<B1-Motion>", resize) separator.pack(side=tk.TOP, fill=tk.X) template = tk.Listbox(frame_navigator, exportselection=False) # 移除expand参数 template.pack(side=tk.TOP, fill=tk.BOTH) frame_navigator.pack(side=tk.TOP, expand=1, fill=tk.BOTH) window.mainloop()
修改说明
- 新增拖拽起始状态记录逻辑,通过
event.y_root获取全局鼠标坐标计算位移差,避免尺寸跳变 - 移除两个子控件的
expand=1参数,避免pack布局覆盖手动设置的高度值 - 增加高度边界校验,确保两个控件高度不会小于20像素,避免布局错乱
- 高度计算引入分隔符自身高度,避免两个控件总高度超出父容器范围
内容的提问来源于stack exchange,提问作者Javid Shiriyev
相关产品推荐
相关产品推荐

