如何在tkinter组件动态增减时自动调整窗口大小并固定底部按钮
要实现动态调整窗口高度+关闭按钮固定底部的需求,核心是替换当前使用的place绝对定位布局,改用流式布局让Tkinter可以自动计算所有可见组件的总尺寸,修改后的可运行代码如下:
import tkinter as tk class Application(tk.Tk): def __init__(self): super().__init__() self.title('test') # 固定窗口宽度为500,高度后续动态调整 self.window_width = 500 # 上层内容容器,存放所有可选组件 self.content_frame = tk.Frame(self) self.content_frame.pack(fill=tk.X, padx=40, pady=20) # 初始固定组件 row1 = tk.Frame(self.content_frame) row1.pack(fill=tk.X, pady=5) tk.Label(row1, text='Prescribed dose :').pack(side=tk.LEFT) self.e1 = tk.Entry(row1, width=10, fg="blue", bd=3) self.e1.pack(side=tk.RIGHT) row2 = tk.Frame(self.content_frame) row2.pack(fill=tk.X, pady=5) tk.Label(row2, text='Is there another target ?').pack(side=tk.LEFT) self.radioValueOuiNonPourBoostPresent = tk.IntVar() tk.Radiobutton(row2, text='Yes', variable=self.radioValueOuiNonPourBoostPresent, value=1, command=self.create_firstWidget).pack(side=tk.LEFT, padx=20) tk.Radiobutton(row2, text='No', variable=self.radioValueOuiNonPourBoostPresent, value=2, command=self.hide_selection).pack(side=tk.LEFT) # 第一层级可选组件容器 self.first_level_frame = tk.Frame(self.content_frame) # 第二层级可选组件容器 self.second_level_frame = tk.Frame(self.content_frame) # 底部固定关闭按钮 self.c2 = tk.Button(self, text='Quit', fg='White', bg='dark green', height=1, width=10, command=self.destroy) self.c2.pack(side=tk.BOTTOM, pady=15) # 初始窗口自适应大小 self.update_window_height() def create_firstWidget(self): if self.radioValueOuiNonPourBoostPresent.get() == 1: # 清空容器避免重复创建组件 for widget in self.first_level_frame.winfo_children(): widget.destroy() # 填充第一层级组件 row1 = tk.Frame(self.first_level_frame) row1.pack(fill=tk.X, pady=5) tk.Label(row1, text='Prescribed dose of the 2nd target :').pack(side=tk.LEFT) self.doseBoost = tk.StringVar(self) tk.Entry(row1, textvariable=self.doseBoost, width=10, fg="blue", bd=3).pack(side=tk.RIGHT) row2 = tk.Frame(self.first_level_frame) row2.pack(fill=tk.X, pady=5) tk.Label(row2, text='Is it a sequential scheme ?').pack(side=tk.LEFT) self.rdioOuiNonSequentiel = tk.IntVar() tk.Radiobutton(row2, text='Yes', variable=self.rdioOuiNonSequentiel, value=1, command=self.create_secondtWidget).pack(side=tk.LEFT, padx=20) tk.Radiobutton(row2, text='No', variable=self.rdioOuiNonSequentiel, value=2, command=self.hide_selection2).pack(side=tk.LEFT) self.first_level_frame.pack(fill=tk.X, pady=5) self.update_window_height() def create_secondtWidget(self): if self.rdioOuiNonSequentiel.get() == 1: for widget in self.second_level_frame.winfo_children(): widget.destroy() row = tk.Frame(self.second_level_frame) row.pack(fill=tk.X, pady=5) tk.Label(row, text='Number of fractions').pack(side=tk.LEFT) self.nombreFractionsBoost = tk.StringVar(self) tk.Entry(row, textvariable=self.nombreFractionsBoost, width=10, fg="blue", bd=3).pack(side=tk.RIGHT) self.second_level_frame.pack(fill=tk.X, pady=5) self.update_window_height() def hide_selection(self): if self.radioValueOuiNonPourBoostPresent.get() == 2: self.first_level_frame.pack_forget() self.second_level_frame.pack_forget() self.update_window_height() def hide_selection2(self): if self.rdioOuiNonSequentiel.get() == 2: self.second_level_frame.pack_forget() self.update_window_height() def update_window_height(self): # 刷新组件布局,获取最新的所需高度 self.update() # 计算当前所有组件总高度,设置窗口尺寸,宽度固定为500 current_height = self.winfo_reqheight() self.geometry(f"{self.window_width}x{current_height}") if __name__ == "__main__": app = Application() app.mainloop()
本次修改的核心逻辑:
- 用Frame分组管理不同层级的可选组件,显示隐藏直接操作整个Frame即可,不需要逐个处理单个组件
- 关闭按钮单独放在窗口底部,不受上层组件增减的影响,始终固定在最下方
- 每次组件显示/隐藏后,自动计算当前所有可见组件的总高度,调整窗口尺寸,宽度固定为你预设的500px
- 优化了组件判断逻辑,不会出现组件未创建时调用方法报错的问题
内容的提问来源于stack exchange,提问作者Romain
相关产品推荐
相关产品推荐

