Python3 Tkinter多可扩展输入字段实现与数据存储问题咨询
问题分析
核心问题(输入同步、数据集仅1组)
- 问题根源1:所有行的输入框绑定了全局唯一的
tagname/tagtype/triggertag三个StringVar变量,只要其中一个输入框修改,所有绑定同变量的输入框都会同步更新。 - 问题根源2:
datasets列表在for循环内部初始化,每次循环都会清空之前的内容,最终仅保留最后一次循环添加的1条数据。
滚动区域适配问题
当前你用的Listbox仅能展示文本内容,无法直接嵌入输入框、标签这类控件,需要改用Canvas嵌套Frame的可滚动容器方案承载动态生成的输入字段。
修复方案
1. 核心逻辑修复
首先删除全局的tagname/tagtype/triggertag变量定义,在update_command中改为每行单独生成变量,并存入全局列表方便后续取值:
# 全局新增变量,存储每行的输入变量和控件 tag_entries = [] def update_command(): global tag_entries # 先清空之前生成的旧控件 for widget in scroll_frame.winfo_children(): widget.destroy() tag_entries.clear() NumberOfTagsInt = int(NumberOfTags.get()) print("标签数量:", NumberOfTagsInt) datasets = [] # 数据集初始化放到循环外 if NumberOfTagsInt > 0: for number in range(NumberOfTagsInt): # 每行单独创建3个StringVar cur_tagname = StringVar() cur_tagtype = StringVar() cur_triggertag = StringVar() # 存到全局列表,后续保存数据时可以遍历取值 tag_entries.append((cur_tagname, cur_tagtype, cur_triggertag)) rowvar = number # 控件放到可滚动的scroll_frame里,不要放主window listlabel = Label(scroll_frame, text=f"Tag {number+1}") listlabel.grid(row=rowvar,column=0, sticky="E") entry1 = Entry(scroll_frame,textvariable=cur_tagname) entry1.grid(row=rowvar, column=1, sticky=E+W, columnspan = 1) entry2 = Entry(scroll_frame,textvariable=cur_tagtype) entry2.grid(row=rowvar, column=2, sticky=E+W, columnspan = 1) entry3 = Entry(scroll_frame,textvariable=cur_triggertag) entry3.grid(row=rowvar, column=3, sticky=E+W, columnspan = 1) # 保存数据时直接遍历tag_entries即可获取所有行的数值 def save_to_db(): datasets = [] for idx, (name_var, type_var, trigger_var) in enumerate(tag_entries): datasets.append({ "TagNumber": idx+1, "TagName": name_var.get(), "TagType": type_var.get(), "TriggerTag": trigger_var.get() }) # 这里添加你的数据库保存逻辑即可 print(datasets)
2. 可滚动容器实现
在主窗口初始化部分,替换原来Listbox附近的代码,新增Canvas+Frame的滚动容器:
# 替换原来的list1上方的布局代码,新增滚动容器 canvas = Canvas(window) canvas.grid(row=3, column=0, rowspan=6, columnspan=4, sticky=NSEW) sb1 = Scrollbar(window, orient=VERTICAL, command=canvas.yview) sb1.grid(row=3, column=5, rowspan=6, sticky=NS) canvas.configure(yscrollcommand=sb1.set) canvas.bind('<Configure>', lambda e: canvas.configure(scrollregion=canvas.bbox("all"))) # 这个frame就是放动态输入框的容器 scroll_frame = Frame(canvas) canvas.create_window((0, 0), window=scroll_frame, anchor="nw") # 原来的Listbox可以保留用来展示历史数据,放到滚动容器下方即可 list1 = Listbox (window, height=20, width=200) list1.grid(row=9, column=0, rowspan = 25, columnspan = 4) # 原来的Listbox滚动条逻辑保留即可
3. 启动自动回填逻辑
程序启动时从数据库查询上次保存的标签配置,先把标签数量赋值给NumberOfTags输入框,调用update_command生成对应数量的输入框,再遍历tag_entries把数据库存的数值赋值给对应行的StringVar即可。
内容的提问来源于stack exchange,提问作者Kevin Lay
相关产品推荐
相关产品推荐

