Python+Tkinter+SQL:如何在两个Frame之间传递变量?
CRM搜索结果跨Frame传递解决方案
不用全局变量的前提下,推荐通过父组件协调+回调函数的方式实现,核心思路是让负责搜索的Frame不直接依赖结果展示Frame,而是通过父容器传递的回调函数把结果交出去,由父容器通知结果Frame更新。
实现示例(基于Tkinter)
import tkinter as tk import sqlite3 class SearchFrame(tk.Frame): def __init__(self, parent, search_callback, **kwargs): super().__init__(parent, **kwargs) # 接收父容器传递的回调函数 self.search_callback = search_callback # 搜索输入框和按钮 self.query_input = tk.Entry(self, width=30) self.query_input.pack(padx=8, pady=8, side=tk.LEFT) tk.Button(self, text="搜索", command=self.run_search).pack(padx=8, pady=8, side=tk.LEFT) def run_search(self): query_keyword = self.query_input.get().strip() if not query_keyword: return # 执行SQL查询(注意用参数化查询防注入) conn = sqlite3.connect("crm_database.db") cursor = conn.cursor() # 参数化查询避免SQL注入 cursor.execute( "SELECT id, name, phone, email FROM customers WHERE name LIKE ? OR phone LIKE ?", (f"%{query_keyword}%", f"%{query_keyword}%") ) search_results = cursor.fetchall() conn.close() # 通过回调把结果传给父容器 self.search_callback(search_results) class ResultsFrame(tk.Frame): def __init__(self, parent, **kwargs): super().__init__(parent, **kwargs) # 结果展示列表框 self.result_list = tk.Listbox(self, width=80, height=20) self.result_list.pack(fill=tk.BOTH, expand=True, padx=8, pady=8) def refresh_results(self, results): # 清空原有内容并加载新结果 self.result_list.delete(0, tk.END) if not results: self.result_list.insert(tk.END, "未找到匹配的记录") return # 格式化展示每条结果 for idx, record in enumerate(results, 1): self.result_list.insert(tk.END, f"{idx}. ID:{record[0]} | 姓名:{record[1]} | 电话:{record[2]} | 邮箱:{record[3]}") class CRMApplication(tk.Tk): def __init__(self): super().__init__() self.title("简易CRM系统") # 初始化搜索和结果Frame self.search_panel = SearchFrame(self, search_callback=self.update_results_panel) self.search_panel.pack(fill=tk.X, padx=5, pady=5) self.results_panel = ResultsFrame(self) self.results_panel.pack(fill=tk.BOTH, expand=True, padx=5, pady=5) def update_results_panel(self, results): # 父容器中转结果,调用结果Frame的更新方法 self.results_panel.refresh_results(results) if __name__ == "__main__": app = CRMApplication() app.mainloop()
关键说明
- 解耦设计:SearchFrame只负责接收用户输入、执行查询,不需要知道ResultsFrame的存在,完全通过回调传递数据,降低模块间依赖。
- 避免全局变量:所有数据传递通过父容器的方法中转,没有使用全局变量。
- SQL注入防护:示例中使用了参数化查询,不要直接拼接SQL字符串,避免安全风险。
备选方案:自定义事件机制
如果偏好事件驱动的方式,也可以用Tkinter的自定义事件实现:
- 在SearchFrame查询完成后,通过
self.parent.event_generate("<<SearchCompleted>>", data=results)触发自定义事件。 - 在ResultsFrame的初始化方法中绑定事件:
self.parent.bind("<<SearchCompleted>>", self.handle_results),然后实现handle_results方法接收数据并更新界面。
内容的提问来源于stack exchange,提问作者LearnedStudent
相关产品推荐
相关产品推荐

