Tkinter点击按钮新建聊天窗口时多窗口消息接收人错乱问题
问题根因
所有消息错绑最后一个联系人的核心原因是全局变量共用导致的取值错误:
- 你定义的
s是绑定主窗口搜索框的全局StringVar,每次在搜索框输入新内容,这个变量的值就会被覆盖 - 现有逻辑只是在新建聊天窗口时,临时取了一次
s的值设为窗口标题,但发送消息的回调函数Enter_pressed里,每次发消息都会重新调用s.get()取联系人名,这时候取到的永远是搜索框里最后一次输入的内容,不管你在哪个聊天窗口发消息,都会被绑定到这个最后输入的联系人。 - 另外给
Toplevel窗口单独加mainloop()是多余写法,整个Tk程序只需要主窗口启动一次事件循环,多写容易引发窗口响应异常。
修复方案
- 新建聊天窗口时,就把当时输入的联系人名称存为当前聊天窗口的局部变量,后续发消息直接用这个局部变量,不再读取全局的
s - 删除聊天窗口多余的
window.mainloop()调用
修正后代码
只需要修改chating函数即可,其他代码不用动:
def chating(): # 窗口创建时就固定当前联系人,后续不再依赖全局搜索框变量 current_contact = s.get().strip() if not current_contact: return # 输入为空时不打开聊天窗口 window = Toplevel(search) window.title(current_contact) messages = Text(window) messages.pack() input_user = StringVar() input_field = Entry(window, text=input_user) input_field.pack(side=BOTTOM, fill=X) def Enter_pressed(event): input_get = input_field.get().strip() if not input_get: return "break" messages.insert(INSERT, '%s\n' % input_get) # 直接使用当前窗口绑定的固定联系人,不再读全局变量 requests.post(url1, data={'msg': input_get, 'sender': current_contact}).text input_user.set('') return "break" frame = Frame(window) input_field.bind("<Return>", Enter_pressed) frame.pack() # 移除多余的window.mainloop()调用
可选优化建议
- 后续可以把聊天窗口逻辑封装成类,彻底避免全局变量滥用导致的变量覆盖问题
- 网络请求逻辑建议放到子线程执行,否则请求超时或卡住时,整个GUI会直接无响应
内容的提问来源于stack exchange,提问作者sam
相关产品推荐
相关产品推荐

