You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 23:00:17