Tkinter Notebook仅显示数据表顶部内容的问题求助
Tkinter Notebook 数据表内容被截断问题修复方案
开发用于展示数据表的Tkinter Notebook组件时,出现数据表仅显示顶部部分的问题。尝试调整标签页框架及Notebook高度参数、切换pack/grid布局均未解决。以下是问题代码及效果截图:
问题代码
import tkinter as tk from tkinter import ttk, messagebox import os # 假设LEMS_EnergyCalcs是已实现的业务函数 def LEMS_EnergyCalcs(folder, output_path, log_path): return ("trail", {"test_weighted": "unit"}, {"test_weighted": 123.456}, "logs") class LEMSDataCruncher_L2(tk.Frame): def __init__(self, root): tk.Frame.__init__(self, root) # 垂直滚动条 self.canvas = tk.Canvas(self, borderwidth=0, background="#ffffff") self.main_frame = tk.Frame(self.canvas, background="#ffffff") self.vsb = tk.Scrollbar(self, orient="vertical", command=self.canvas.yview) self.canvas.configure(yscrollcommand=self.vsb.set) self.vsb.pack(side="right", fill="y") # 水平滚动条 self.hsb = tk.Scrollbar(self, orient="horizontal", command=self.canvas.xview) self.canvas.configure(xscrollcommand=self.hsb.set) self.hsb.pack(side="bottom", fill="x") self.canvas.pack(side="left", fill="both", expand=True) self.canvas.create_window((8, 8), window=self.main_frame, anchor="nw", tags="main_frame") self.main_frame.bind("<Configure>", self.onFrameConfigure) # 给主容器设置grid权重,确保空间能扩展 self.main_frame.grid_rowconfigure(0, weight=1) self.main_frame.grid_columnconfigure(0, weight=1) # 文件路径输入区 tk.Label(self.main_frame, text="Select Folder:").grid(row=0, column=0) self.folder_path_var = tk.StringVar() self.folder_path = tk.Entry(self.main_frame, textvariable=self.folder_path_var, width=150) self.folder_path.grid(row=0, column=0) self.energy_files = [os.path.join(os.getcwd(), "EnergyInputs.csv")] # 模拟测试路径 # 浏览按钮 browse_button = tk.Button(self.main_frame, text="Browse", command=self.on_browse) browse_button.grid(row=0, column=1) # OK按钮 ok_button = tk.Button(self.main_frame, text="OK", command=self.on_okay) ok_button.grid(row=1, column=0, pady=10) # 鼠标滚轮绑定 self.canvas.bind_all("<MouseWheel>", self.onCanvasMouseWheel) self.pack(side=tk.TOP, fill="both", expand=True) def onFrameConfigure(self, event): # 关键缺失方法:更新画布滚动区域 self.canvas.configure(scrollregion=self.canvas.bbox("all")) def onCanvasMouseWheel(self, event): if event.delta > 0: self.canvas.yview_scroll(-1, "units") elif event.delta < 0: self.canvas.yview_scroll(1, "units") def on_browse(self): # 实现文件夹选择逻辑(省略) pass def on_okay(self): error = [] # 创建Notebook容器 self.notebook = ttk.Notebook(self.main_frame) # 让Notebook占满可用空间 self.notebook.grid(row=2, column=0, sticky="nsew", columnspan=2) self.main_frame.grid_rowconfigure(2, weight=1) for folder in self.energy_files: try: output_path = folder.replace('EnergyInputs.csv', 'EnergyOutputs.csv') log_path = folder.replace('EnergyInputs.csv', 'log.txt') [trail, units, data, logs] = LEMS_EnergyCalcs(folder, output_path, log_path) # 创建标签页框架 tab_frame = tk.Frame(self.notebook) tab_frame.grid_rowconfigure(0, weight=1) tab_frame.grid_columnconfigure(0, weight=1) tab_frame.grid(row=0, column=0, sticky="nsew") # 创建标签页内部容器,避免覆盖主frame变量 tab_inner_frame = tk.Frame(tab_frame, background="#ffffff") tab_inner_frame.grid(row=0, column=0, sticky="nsew") tab_inner_frame.grid_rowconfigure(0, weight=1) tab_inner_frame.grid_columnconfigure(0, weight=1) # 数据保留三位小数 round_data = {} for name in data: try: rounded = round(data[name], 3) except: rounded = data[name] round_data[name] = rounded data = round_data # 生成输出表格 self.create_output_table(data, units, logs, num_columns=150, num_rows=300, folder_path=folder, parent_frame=tab_inner_frame) # 添加标签页 self.notebook.add(tab_frame, text=os.path.basename(os.path.dirname(folder))) except PermissionError: error.append(folder) if error: message = f"One or more files are open in another program. Close them and try again." messagebox.showerror("Error", message) self.notebook.bind("<ButtonRelease-1>", lambda event: self.canvas.yview_moveto(0)) def create_output_table(self, data, units, logs, num_columns, num_rows, folder_path, parent_frame): # 清空容器原有控件 for widget in parent_frame.winfo_children(): widget.destroy() # 创建表格组件 output_table = OutputTable(parent_frame, data, units, logs, num_columns, num_rows, folder_path) output_table.grid(row=0, column=0, sticky="nsew") class OutputTable(tk.Frame): def __init__(self, root, data, units, logs, num_columns, num_rows, folder_path): tk.Frame.__init__(self, root) # 设置自身布局权重 self.grid_rowconfigure(1, weight=1) self.grid_rowconfigure(3, weight=1) self.grid_columnconfigure(0, weight=1) self.grid_columnconfigure(3, weight=1) # 退出按钮 exit_button = tk.Button(self, text="EXIT", command=root.quit, bg="red", fg="white") exit_button.grid(row=0, column=4, padx=(350, 5), pady=5, sticky="e") # 查找输入框 self.find_entry = tk.Entry(self, width=100) self.find_entry.grid(row=0, column=0, padx=0, pady=0, columnspan=3) find_button = tk.Button(self, text="Find", command=self.find_text) find_button.grid(row=0, column=3, padx=0, pady=0) # 修复缺失的text_widget self.text_widget = tk.Text(self, wrap="none", height=num_rows, width=110) self.text_widget.tag_configure("bold", font=("Helvetica", 12, "bold")) self.text_widget.grid(row=1, column=0, padx=0, pady=10, columnspan=4, sticky="nsew") # 主表格标题 header = "{:<110}|".format("ALL ENERGY OUTPUTS") self.text_widget.insert(tk.END, header + "\n" + "_" * 63 + "\n", "bold") header = "{:<64} | {:<31} | {:<18} |".format("Variable", "Value", "Units") self.text_widget.insert(tk.END, header + "\n" + "_" * 63 + "\n", "bold") # 加权指标表格 self.cut_table = tk.Text(self, wrap="none", height=num_rows, width=72) self.cut_table.tag_configure("bold", font=("Helvetica", 12, "bold")) self.cut_table.grid(row=3, column=0, padx=0, pady=10, columnspan=4, sticky="nsew") cut_header = "{:<113}|".format("WEIGHTED METRICS") self.cut_table.insert(tk.END, cut_header + "\n" + "_" * 63 + "\n", "bold") cut_header = "{:<64} | {:<31} | {:<18} |".format("Variable", "Value", "Units") self.cut_table.insert(tk.END, cut_header + "\n" + "_" * 63 + "\n", "bold") # 填充加权指标数据 for key, value in data.items(): unit = units.get(key, "") val = value if value else " " unit = unit if unit else " " if key.endswith('weighted'): row = "{:<35} | {:<17} | {:<10} |".format(key, val, unit) self.cut_table.insert(tk.END, row + "\n") self.cut_table.insert(tk.END, "_" * 70 + "\n") def find_text(self): # 实现查找逻辑(省略) pass if __name__ == "__main__": root = tk.Tk() root.geometry("1200x800") app = LEMSDataCruncher_L2(root) root.mainloop()
原问题效果截图

核心修复点
- 补全滚动区域更新方法:添加
onFrameConfigure方法,让画布能感知内容变化并更新滚动范围。 - 避免变量覆盖:原代码中用
self.frame重写主容器变量,导致滚动绑定失效,改用独立变量存储标签页内容器。 - 配置布局权重:所有容器通过
grid_rowconfigure和grid_columnconfigure设置weight=1,并添加sticky="nsew"确保控件随父容器扩展。 - 修复缺失控件:补充
OutputTable中未创建的self.text_widget,并正确设置其布局属性。 - 调整Notebook布局:将Notebook放在独立行并设置权重,确保它能占据剩余显示空间。
内容的提问来源于stack exchange,提问作者Jaden B
相关产品推荐
相关产品推荐

