如何在CustomTkinter中创建可编辑坐标表格(无需类)?
CustomTkinter 坐标表格实现(无类版)
一、先解决文本框读取问题
你之前用文本框存单个坐标读不到值,核心是没用到CustomTkinter输入框的.get()方法,以下是基础读取示例:
import customtkinter as ctk ctk.set_appearance_mode("light") ctk.set_default_color_theme("blue") app = ctk.CTk() app.title("单坐标读取测试") # 单个坐标输入框 x_entry = ctk.CTkEntry(app, placeholder_text="X坐标") x_entry.pack(pady=5) y_entry = ctk.CTkEntry(app, placeholder_text="Y坐标") y_entry.pack(pady=5) def read_coords(): # 读取输入框值并转换为整数,可根据需求改为float try: x = int(x_entry.get()) y = int(y_entry.get()) print(f"读取到坐标:({x}, {y})") except ValueError: print("请输入有效的数字坐标") read_btn = ctk.CTkButton(app, text="读取坐标", command=read_coords) read_btn.pack(pady=10) app.mainloop()
二、实现可存储/读取/修改的坐标表格
CustomTkinter没有原生表格控件,我们可以用CTkScrollableFrame嵌套输入框模拟表格,实现坐标的增删改查,且全程不用类:
import customtkinter as ctk ctk.set_appearance_mode("light") ctk.set_default_color_theme("blue") app = ctk.CTk() app.title("坐标管理表格") app.geometry("450x400") # 初始坐标列表(模拟Canvas上已绘制的点) coords_list = [(100, 200), (150, 250), (200, 300)] # 存储每行的输入框控件,方便后续同步修改 entry_rows = [] # 创建带滚动的表格容器 table_frame = ctk.CTkScrollableFrame(app, width=430, height=300) table_frame.pack(pady=10, padx=10, fill="both", expand=True) def update_coords(row_idx, axis): """同步输入框修改到坐标列表""" try: val = int(entry_rows[row_idx][axis].get()) if axis == 0: coords_list[row_idx] = (val, coords_list[row_idx][1]) else: coords_list[row_idx] = (coords_list[row_idx][0], val) print(f"坐标已更新:{coords_list[row_idx]}") except ValueError: # 输入无效时恢复原数值 entry_rows[row_idx][axis].delete(0, "end") entry_rows[row_idx][axis].insert(0, str(coords_list[row_idx][axis])) def create_row(x, y, row_idx): """创建一行坐标输入控件""" # 行标签 label = ctk.CTkLabel(table_frame, text=f"点 {row_idx+1}") label.grid(row=row_idx, column=0, padx=5, pady=5, sticky="w") # X坐标输入框 x_entry = ctk.CTkEntry(table_frame, width=120) x_entry.insert(0, str(x)) x_entry.grid(row=row_idx, column=1, padx=5, pady=5) x_entry.bind("<FocusOut>", lambda e: update_coords(row_idx, 0)) # Y坐标输入框 y_entry = ctk.CTkEntry(table_frame, width=120) y_entry.insert(0, str(y)) y_entry.grid(row=row_idx, column=2, padx=5, pady=5) y_entry.bind("<FocusOut>", lambda e: update_coords(row_idx, 1)) # 删除按钮 del_btn = ctk.CTkButton(table_frame, text="删除", width=80, command=lambda: delete_row(row_idx)) del_btn.grid(row=row_idx, column=3, padx=5, pady=5) entry_rows.append([x_entry, y_entry]) def delete_row(row_idx): """删除指定行坐标""" coords_list.pop(row_idx) # 销毁该行所有控件 for widget in table_frame.grid_slaves(row=row_idx): widget.destroy() entry_rows.pop(row_idx) # 更新后续行的标签和绑定事件 for i in range(row_idx, len(coords_list)): # 更新行号标签 label = table_frame.grid_slaves(row=i)[0] label.configure(text=f"点 {i+1}") # 重新绑定输入框事件 x_entry = entry_rows[i][0] y_entry = entry_rows[i][1] x_entry.unbind("<FocusOut>") x_entry.bind("<FocusOut>", lambda e, idx=i: update_coords(idx, 0)) y_entry.unbind("<FocusOut>") y_entry.bind("<FocusOut>", lambda e, idx=i: update_coords(idx, 1)) # 更新删除按钮命令 del_btn = table_frame.grid_slaves(row=i)[-1] del_btn.configure(command=lambda idx=i: delete_row(idx)) def add_new_point(): """新增一个坐标点(默认(0,0),可改为Canvas新绘制点的坐标)""" coords_list.append((0, 0)) create_row(0, 0, len(coords_list)-1) def print_all_coords(): """输出所有坐标,验证读取结果""" print("\n当前所有坐标:") for idx, (x, y) in enumerate(coords_list): print(f"点 {idx+1}: ({x}, {y})") # 初始化表格行 for idx, (x, y) in enumerate(coords_list): create_row(x, y, idx) # 操作按钮区域 btn_frame = ctk.CTkFrame(app) btn_frame.pack(pady=5, padx=10, fill="x") add_btn = ctk.CTkButton(btn_frame, text="新增点", command=add_new_point) add_btn.pack(side="left", padx=5, pady=5) print_btn = ctk.CTkButton(btn_frame, text="查看所有坐标", command=print_all_coords) print_btn.pack(side="right", padx=5, pady=5) app.mainloop()
核心说明
- 输入框读取:通过
.get()方法获取输入值,记得处理类型转换和无效输入 - 表格模拟:用
CTkScrollableFrame实现滚动效果,每行包含标签、输入框和操作按钮 - 数据同步:给输入框绑定
<FocusOut>事件,失去焦点时自动将修改同步到坐标列表 - 无类实现:全程用全局变量管理数据和控件,符合你的需求
内容的提问来源于stack exchange,提问作者Jozef Bezák
相关产品推荐
相关产品推荐

