如何实现点击Tkinter Label控件打开sqlite3存储的对应用户详情?
问题解答
首先明确:不需要类也能实现功能,但使用类是更优的选择
你现在的代码遇到的问题大部分和用不用类无关,先解决现有非面向对象代码的bug就能跑通:
现有代码的3个核心问题
- 循环绑定按钮的lambda存在闭包迟绑定问题:所有按钮点击后都会传入最后一条用户记录的参数
- 弹出窗口错误使用
Tk():子窗口应该用Toplevel(),避免多主窗口消息循环异常 open_user函数仅接收用户名,无法查询/展示用户的其他详细字段(税号、手机号等)
非面向对象的可运行修改版本
from tkinter import * import sqlite3 root = Tk() root.title("Utenti") # 注意Windows路径斜杠要转义或者用原始字符串 root.iconbitmap(r"D:\Willow\WilloW SW Gestionale") root.geometry("365x600") def open_user(user_record): # 子窗口用Toplevel不要用Tk user = Toplevel() user.title(f"用户详情:{user_record[0]}") user.iconbitmap(r"D:\Willow\WilloW SW Gestionale") user.geometry("500x400") # 直接用传进来的整条记录填值就行,或者也可以拿user_record[-1](oid)去数据库重新查 # create entry f_name_entry = Entry(user, width=30) f_name_entry.insert(0, user_record[0]) f_name_entry.config(state="disabled") f_name_entry.grid(row=0, column=1, padx=20, pady=(10, 0)) # 这里P_iva对应你数据库的第二个字段,按你实际表结构调整索引就行 P_iva_entry = Entry(user, width=30) P_iva_entry.insert(0, user_record[1]) P_iva_entry.config(state="disabled") P_iva_entry.grid(row=1, column=1) cell_number_entry = Entry(user, width=30) cell_number_entry.insert(0, user_record[2]) cell_number_entry.config(state="disabled") cell_number_entry.grid(row=2, column=1) tax_entry = Entry(user, width=30) tax_entry.insert(0, user_record[3]) tax_entry.config(state="disabled") tax_entry.grid(row=3, column=1) inps_entry = Entry(user, width=30) inps_entry.insert(0, user_record[4]) inps_entry.config(state="disabled") inps_entry.grid(row=4, column=1) # create labels f_name_label = Label(user, text="用户名") f_name_label.grid(row=0, column=0, pady=(10, 0)) P_iva_label = Label(user, text="p iva") P_iva_label.grid(row=1, column=0) cell_number_label = Label(user, text="cell number") cell_number_label.grid(row=2, column=0) tax_label = Label(user, text="tax") tax_label.grid(row=3, column=0) inps_label = Label(user, text="inps") inps_label.grid(row=4, column=0) i = 4 conn = sqlite3.connect("usersEsteso.db") c = conn.cursor() c.execute("SELECT *, oid FROM usersEsteso") records = c.fetchall() conn.close() # 查完就可以关了不需要留着 for record in records: users_lable = Label(root, bg="#778899") users_lable.grid(row=i + 7, column=0, sticky="w", padx=5, pady=5, columnspan=3) user_text = Label(users_lable, text=record[0]) user_text.grid(row=0, column=0, pady=5, padx=5, sticky="w") # lambda用默认参数提前绑定当前循环的record openUser_lable_button = Button(users_lable, text="apri " + record[0], command=lambda r=record: open_user(r)) openUser_lable_button.grid(row=1, column=0, pady=5, padx=5, sticky="e") i = i + 1 root.mainloop()
为什么更推荐用类实现
当你后续要加功能(比如编辑用户信息、删除用户、刷新用户列表)的时候,平铺的代码会出现大量全局变量,逻辑耦合度极高,用类可以把主窗口、用户详情窗口的逻辑、数据都封装起来,代码可读性和可维护性会高很多,也不容易出现变量污染的问题。
内容的提问来源于stack exchange,提问作者Gianni Panni
相关产品推荐
相关产品推荐

