Python用tkinter/tksheet构建固定大小数据表时sheet_display_dimensions报错如何解决
Tksheet固定大小表格初始化问题说明
开发背景
我正在基于Tkinter生态的Tksheet扩展库构建支持任意数量标签页的类电子表格界面,要求表格大小由用户指定、初始化后固定,用户可通过Excel复制粘贴或直接在单元格输入的方式填充数据。
现有API调用问题
目前我尝试使用Tksheet提供的两类官方API初始化i行j列的空表格,均触发异常或不符合预期:
- 调用
set_sheet_data_and_display_dimensions(total_rows = None, total_columns = None)时抛出TypeError,错误触发于GetLinesHeight(self, n, old_method = False)方法:该方法要求入参n为整数,但调用方sheet_display_dimensions的对应代码行height = self.MT.GetLinesHeight(self.MT.default_rh)传入的MT.default_rh可能为字符串或元组类型,其他Tksheet方法会对该参数做整数转换处理,但sheet_display_dimensions缺少该逻辑。 - 调用
sheet_data_dimensions(total_rows = None, total_columns = None)时,程序层面的表格维度设置生效,但不会触发前端渲染,用户看不到调整后的表格;补充调用sheet_display_dimensions(i,j)同样会触发上述类型错误。
可用的替代实现方案
可以绕过存在逻辑缺陷的维度设置API,使用行列插入的方法实现固定大小表格初始化:
Tksheet默认初始化生成1行0列的空表格,因此只需额外插入j列、i-1行即可得到指定的i行j列空表格,对应实现代码如下:
# 其中i为目标行数,j为目标列数 test.sheet.insert_columns(j) test.sheet.insert_rows(i - 1)
该方法不会触发类型错误,且表格维度和渲染效果均符合预期。
完整测试代码
from tksheet import Sheet import tkinter as tk from tkinter import ttk import tkinter.simpledialog as sd # 原代码遗漏的依赖,补充后可正常运行列名修改功能 # 该类用于构建并展示测试表格,仅用于问题复现,不属于问题核心部分 class SeriesTable(tk.Frame): def __init__(self, master): super().__init__(master) # 调用父类初始化方法构建框架 self.grid_columnconfigure(0, weight=1) # 配置窗口缩放规则 self.grid_rowconfigure(0, weight=1) self.grid(row=0, column=0, sticky="nswe") self.sheet = Sheet(self, data=[[]]) # 在框架内初始化空表格 self.sheet.grid(row=0, column=0, sticky="nswe") self.sheet.enable_bindings(bindings= # 启用表格交互能力 ("single_select", "select_all", "column_select", "row_select", "drag_select", "arrowkeys", "column_width_resize", "double_click_column_resize", "row_height_resize", "double_click_row_resize", "right_click_popup_menu", "rc_select", # rc = 右键点击 "copy", "cut", "paste", "delete", "undo", "edit_cell" )) # 注意:修改表格结构/大小的操作(如插入/删除行列)已被禁用 # 确保粘贴操作不会改变表格大小 self.sheet.set_options(expand_sheet_if_paste_too_big=False) # 绑定自定义事件处理函数 self.sheet.extra_bindings("end_edit_cell", func=self.cell_edited) self.sheet.extra_bindings("end_paste", func=self.cells_pasted) label = "修改列名" # 为列头右键菜单增加自定义选项 self.sheet.popup_menu_add_command(label, self.column_header_change, table_menu=False, index_menu=False, header_menu=True) # 事件处理函数 def cell_edited(self, info_tuple): r, c, key_pressed, updated_value = info_tuple # 拆解事件参数 ''' 此处校验updated_value合法性 ''' # 校验通过 pass # 执行后续业务逻辑 def cells_pasted(self, info_tuple): key_pressed, rc_tuple, updated_array = info_tuple # 拆解事件参数 r, c = rc_tuple # 粘贴起始行列号 err_flag = False # 校验错误标记 ''' 此处校验updated_array合法性 ''' # 校验完成 if err_flag: # 校验不通过 self.sheet.undo() # 撤销粘贴操作 else: pass # 执行后续业务逻辑 def column_header_change(self): r, c = self.sheet.get_currently_selected() col_name = sd.askstring("用户输入", "请输入列名:") if col_name is not None and col_name != "": # 用户取消或输入为空时不执行操作 self.sheet.headers([col_name], index=c) # 该方法存在问题,始终修改第一列 self.sheet.redraw() # 以下为测试代码 tk_win = tk.Tk() # 初始化Tkinter根窗口 tk_win.title("Master Sequence") tk_win.geometry("600x400") tk_win.config(bg='red') nb = ttk.Notebook(tk_win) # ttk的Notebook组件为标签页容器 nb.pack(expand=True, fill='both') # 组件布局配置 settings_page = tk.Frame(nb) # 初始化第一个标签页 nb.add(settings_page, text = "设置") # 将标签页加入容器 test = SeriesTable(nb) # 创建1行0列的测试表格 nb.add(test, text = "表格测试") # 将表格页加入容器 i = 4 j = 3 #test.sheet.set_sheet_data_and_display_dimensions(total_rows=i, total_columns=j) # 抛出TypeError #test.sheet.sheet_data_dimensions(total_rows=i, total_columns=j) # 表格维度扩展为4x3,但显示仍为1x0 #test.sheet.sheet_display_dimensions(total_rows=i, total_columns=j) # 抛出TypeError test.sheet.insert_columns(j) # 该方法可正常执行 test.sheet.insert_rows(i - 1) # 注意原有1行,需插入i-1行 test.mainloop()
内容的提问来源于stack exchange,提问作者Ilan Sharon
相关产品推荐
相关产品推荐

