从MySQL表填充Tkinter Listbox及实现搜索自动补全的代码修正求助
问题分析与代码修正
核心问题点
- 列表嵌套错误:你用
self.medlist.append(self.medres)把fetchall()返回的元组列表整个塞进了medlist,导致medlist变成嵌套结构(比如[[('Insulin a',), ('Insulin b',)]]),循环时只能取到外层列表的第一个元素。 - update函数逻辑错误:函数接收了
data参数,但实际循环的是self.medlist,且因原列表是嵌套元组,只取了第一个元素的索引0,导致仅显示一条数据。 - 搜索匹配逻辑错误:遍历嵌套的
medlist时,实际遍历的是外层列表而非单个药品名称,导致匹配判断失效。
修正后的完整代码
import tkinter as tk import customtkinter as ck import os # 确保pr是已正确初始化的MySQL连接实例 ck.set_appearance_mode("Light") # Modes: "System" (standard), "Dark", "Light" ck.set_default_color_theme("green") # Themes: "blue" (standard), "green", "dark-blue" PATH = os.path.dirname(os.path.realpath(__file__)) class entrywin(ck.CTk): WIDTH = 950 HEIGHT = 700 WIDTHIMG = 600 HEIGHTIMG = 200 medboxlist = [] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.title("Prescription Manager 1.0.0") # self.iconbitmap('C:\Syfar Projects\logo.ico') self.geometry(f"{entrywin.WIDTH}x{entrywin.HEIGHT}") self.protocol("WM_DELETE_WINDOW", self.exitcommand) self.resizable(False, False) self.grid_columnconfigure(1, weight=1) self.grid_rowconfigure(0, weight=1) self.frame_left = ck.CTkFrame(master=self, width=180, corner_radius=0) self.frame_left.grid(row=0, column=0, sticky="nswe") self.frame_right = ck.CTkFrame(master=self) self.frame_right.grid(row=0, column=1, sticky="nswe", padx=20, pady=20) # ============ frame_left 布局配置 ============ self.frame_left.grid_rowconfigure(0,) self.frame_left.grid_rowconfigure(1,) self.frame_left.grid_rowconfigure(2,) self.frame_left.grid_rowconfigure(3,) self.med_label = ck.CTkLabel(master=self.frame_right, width=10, text='Φάρμακο:', text_font=("Roboto Medium", -16)) self.med_label.grid(row=8, column=0, pady=10, padx=130, sticky="w") self.med_ent = ck.CTkEntry(master=self.frame_right, width=200, ) self.med_ent.bind('<KeyRelease>', self.checkls) self.med_ent.grid(row=8, column=0, padx=210, pady=0, sticky="w") self.med_box = tk.Listbox(master=self.frame_right, height=5) # 从数据库获取数据并转换为纯字符串列表 pr.cur.execute('SELECT Description FROM meds') self.medres = pr.cur.fetchall() self.medlist = [item[0] for item in self.medres] print(self.medlist) self.update(self.medlist) # 初始化填充列表框 self.med_box.bind('<<ListboxSelect>>', self.filent) self.med_box.grid(row=9, column=0, padx=210, sticky='w') def update(self, data): self.med_box.delete(0, tk.END) # 遍历传入的data参数,逐个插入列表框 for item in data: self.med_box.insert(tk.END, item) def filent(self, event): self.med_ent.delete(0, tk.END) self.med_ent.insert(0, self.med_box.get(ACTIVE)) def checkls(self, event): self.typed = self.med_ent.get().strip() if not self.typed: self.data = self.medlist else: self.data = [] # 遍历纯字符串列表,执行大小写不敏感的模糊匹配 for item in self.medlist: if self.typed.lower() in item.lower(): self.data.append(item) self.update(self.data) def exitcommand(self, event=0): self.destroy() if __name__ == "__main__": main = entrywin() main.mainloop()
关键修正说明
- 数据库数据处理:用列表推导式
[item[0] for item in self.medres]把fetchall()返回的元组列表转换成纯药品名称的字符串列表,避免嵌套和元组处理的冗余操作。 - update函数:改为遍历传入的
data参数,直接插入每个药品名称,确保列表框显示所有匹配结果。 - 搜索逻辑:遍历纯字符串的
medlist,直接对每个药品名称做大小写不敏感的模糊匹配,确保搜索功能正常触发。
内容的提问来源于stack exchange,提问作者Nikolaos Gasparis
相关产品推荐
相关产品推荐

