如何在Tkinter中基于更新后的数据重新绘制Label与Entry控件?
解决Tkinter控件切换时叠加/残留的问题
你的问题核心是全局变量未正确更新和控件列表未清空导致的GUI刷新异常,以下是具体修复方案:
问题根源
- 切换列表时,函数内创建的
frm_ent_bilans是局部变量,未关联到全局框架,导致新框架无法显示,旧框架的控件残留 entry_list_bilans每次添加新Entry但未清空,导致后续生成文本时会读取旧控件的数据lst_bilans在函数内被重新赋值为局部变量,全局列表未更新,生成文本时仍用旧数据
修复步骤
- 在切换函数中用
global声明要修改的全局变量,确保修改的是全局对象 - 每次切换前清空
entry_list_bilans,避免旧控件引用残留 - 新创建的框架必须调用
grid方法布局到正确位置 - 封装控件生成逻辑,减少重复代码
修改后的完整代码
import tkinter as tk import re import pyperclip import textwrap from tkmacosx import Button from tkinter import ttk import random window=tk.Tk() window.title("Myszkoprogram, ver 1.2") tab_control = ttk.Notebook(master=window) tab_control.grid(row=0, column=0) tab1 = ttk.Frame(master=tab_control) tab2 = ttk.Frame(master=tab_control) def validate_input(text): return re.match("^[0-9,]*$", text) is not None vcmd = (window.register(validate_input), "%P") dash = '–' opis_przycisku_2 = textwrap.fill("Usuń zawartość komórek", width=20) tab_control.add(tab1, text = "Morfologia i biochemia") tab_control.add(tab2, text = "Bilans płynów") liczba_drenow=1 lst_bilans_1 = ["Płyny dożylne", "Płyny doustne", "Sonda", "Dreny", "Mocz"] lst_bilans_2 = ["PFFFF", "DADAWDW", "Sonda", "L", "P", "Mocz", "MALAKAKAKAAA", "BLAAAAH"] lst_bilans=lst_bilans_1 lst_bilans_unit="ml" lst_words_for_bilans=["zanotowano", "wpisano", "zapisano", "napisano"] frm_bilans_part = tk.Frame(master=tab2) frm_bilans_part.grid(row=0, column=0) frm_full_data_bilans = tk.Frame(master=frm_bilans_part) frm_full_data_bilans.grid(row=0, column=0) frm_btn_bilans = tk.Frame(master=frm_bilans_part) frm_btn_bilans.grid(row=0, column=1) frm_text_bilans = tk.Frame(master=frm_bilans_part) frm_text_bilans.grid(row=0, column=2) lbl_info_bilans = tk.Label(master=frm_full_data_bilans, text="Bilans płynów:") lbl_info_bilans.grid(row=0, column=0) frm_ent_bilans = tk.Frame(master=frm_full_data_bilans) frm_ent_bilans.grid(row=1, column=0) entry_list_bilans=[] def paint_entry(target_list): # 清空控件列表 entry_list_bilans.clear() # 生成新的Label和Entry for idx, value in enumerate(target_list): lbl_bilans=tk.Label(master=frm_ent_bilans, text=value + ":") lbl_bilans.grid(row=idx, column=0) ent_bilans=tk.Entry(master=frm_ent_bilans, validate="key", validatecommand=vcmd) ent_bilans.grid(row=idx, column=1) entry_list_bilans.append(ent_bilans) paint_entry(lst_bilans) def create_bilans(): data_bilans = str() values = [ent.get() for ent in entry_list_bilans] for idx, value in enumerate(values): if value == "": continue else: data_bilans = data_bilans + lst_bilans[idx] + " {0} " + value + " " + lst_bilans_unit + ", " if data_bilans: data_bilans = "W bilansie wodnym {1}: " + data_bilans[:len(data_bilans)-2] + "." else: data_bilans = str() random_word = random.choice(lst_words_for_bilans) variables_for_data_bilans = [dash, random_word] data_bilans = data_bilans.format(*variables_for_data_bilans) pyperclip.copy(data_bilans) wrapped_data_bilans = textwrap.fill(data_bilans, width=75) lbl_text_bilans["text"] = wrapped_data_bilans def remove_text_bilans(): for ent in entry_list_bilans: ent.delete(0, tk.END) def change_dren_number_to_1(): global frm_ent_bilans, lst_bilans # 销毁旧框架 frm_ent_bilans.destroy() # 创建新框架并布局 frm_ent_bilans = tk.Frame(master=frm_full_data_bilans) frm_ent_bilans.grid(row=1, column=0) # 更新全局列表 lst_bilans = lst_bilans_1 # 生成新控件 paint_entry(lst_bilans) def change_dren_number_to_2(): global frm_ent_bilans, lst_bilans frm_ent_bilans.destroy() frm_ent_bilans = tk.Frame(master=frm_full_data_bilans) frm_ent_bilans.grid(row=1, column=0) lst_bilans = lst_bilans_2 paint_entry(lst_bilans) frm_funct_btn_bilans = tk.Frame(master=frm_btn_bilans) frm_funct_btn_bilans.grid(row=1, column=0) frm_number_of_dren_bilans = tk.Frame(master=frm_btn_bilans) frm_number_of_dren_bilans.grid(row=0, column=0) opis_przycisku_1_bilans = textwrap.fill("Utwórz tekst i skopiuj do schowka", width=20) text_convert_bilans = Button(master = frm_funct_btn_bilans, text= opis_przycisku_1_bilans, command = create_bilans, bg='#ADEFD1', fg='#00203F', borderless=1, width=150) text_convert_bilans.grid(row=0, column=0, pady=80) btn_remove_bilans = Button(master=frm_funct_btn_bilans, text = opis_przycisku_2, command = remove_text_bilans, bg='#E69A8D', fg='#5F4B8B', borderless=1, width=150, activebackground=('#AE0E36', '#D32E5E'), activeforeground='#E69A8D') btn_remove_bilans.grid(row=1, column=0, pady=80) opis_przycisku_3_bilans = textwrap.fill(("Liczba drenów {0} 2").format(dash)) btn_change_dren_to_2 = Button(master=frm_number_of_dren_bilans, text = opis_przycisku_3_bilans, command = change_dren_number_to_2) btn_change_dren_to_2.grid(row=0, column=0, pady=80) opis_przycisku_4_bilans = textwrap.fill(("Liczba drenów {0} 1").format(dash)) btn_change_dren_to_1 = Button(master=frm_number_of_dren_bilans, text = opis_przycisku_4_bilans, command = change_dren_number_to_1) btn_change_dren_to_1.grid(row=0, column=1, pady=80) lbl_text_bilans = tk.Label(master=frm_text_bilans, width=55) lbl_text_bilans.grid(row=0, column=0) window.mainloop()
关键修改点说明
- 新增
paint_entry函数,统一处理控件生成逻辑,每次调用前清空entry_list_bilans - 切换函数中添加
global声明,确保修改全局的frm_ent_bilans和lst_bilans - 新框架创建后立即调用
grid(row=1, column=0),确保显示在正确位置 - 销毁旧框架后,新框架会完全替代旧位置的控件,不会出现叠加残留
内容的提问来源于stack exchange,提问作者Łukasz Kwasik
相关产品推荐
相关产品推荐

