为何执行while循环后Tkinter窗口仍关闭?已调用quit和update
问题描述
我使用Python的socket和tkinter库开发一款双人连接应用,目前遇到的问题是无法让Tkinter窗口按预期消失(下一步计划实现双人聊天窗口)。我已将相关逻辑放在线程中,主进程运行mainloop,即使在socket的while循环前调用了window.quit()和window.update(),循环结束后窗口仍会关闭。目前暂时不关注窗口冻结问题。
主函数代码
from tkinter import * import threading from hosting import getHostAddress, getConnected from client import connectToHost def hostServer(): hostB.destroy() connectB.destroy() e.destroy() addr, sock = getHostAddress() hostingText = addr + "\nWaiting for Connection" hostLabel = Label(window, text=hostingText) hostLabel.pack() getConnected(sock, window) def connectToIP(): IP = e.get() window.destroy() connectToHost(IP) def connectServer(): hostB.destroy() connectB.destroy() conLabel = Label(window, text="Enter Code") conLabel.pack(side="left") e.pack(side="left") window.geometry("250x50") conButton = Button(window, text="Connect", command=connectToIP) conButton.pack(side="left") if __name__ =="__main__": window = Tk() e = Entry(window) hostB = Button(window, text="Host", command=threading.Thread(target=hostServer).start) hostB.pack() connectB = Button(window, text="Connect", command=connectServer) connectB.pack() window.mainloop()
client.py
import socket port = 5000; client = socket.socket() def connectToHost(IPAddr): client.connect((IPAddr, port)) message = input(" -> ") # take input while message.lower().strip() != 'bye': client.send(message.encode()) # send message data = client.recv(1024).decode() # receive response print('Received from server: ' + data) # show in terminal message = input(" -> ") # again take input client.close() # close the connection
hosting.py
import socket #def getPort(): def getHostAddress(): hostname = socket.gethostname() IPAddr = socket.gethostbyname(hostname) sock = socket.socket() sock.bind((hostname, 5000)) addr = IPAddr return addr, sock def getConnected(sock, window): sock.listen(2) conn, address = sock.accept() # accept new connection window.quit() window.update() while True: # receive data stream. it won't accept data packet greater than 1024 bytes data = conn.recv(1024).decode() if not data: # if data is not received break break print("from connected user: " + str(data)) data = input(' -> ') conn.send(data.encode()) # send data to the client conn.close() # close the connection
解决方案
核心问题
window.quit()仅终止Tkinter的mainloop(),但不会销毁窗口对象。主线程退出mainloop()后,程序仍会等待子线程中的socket循环结束,此时窗口处于无主循环管理的状态,等线程结束程序退出时窗口才会关闭。
修改方案
- 替换窗口关闭方式:在
hosting.py的getConnected函数中,用window.destroy()替代window.quit()和window.update(),直接销毁窗口:
def getConnected(sock, window): sock.listen(2) conn, address = sock.accept() # accept new connection # 直接销毁窗口,而非终止主循环 window.destroy() while True: data = conn.recv(1024).decode() if not data: break print("from connected user: " + str(data)) data = input(' -> ') conn.send(data.encode()) conn.close()
- 修复线程启动隐患:主函数中按钮的
command参数直接调用start()会导致线程提前执行,改用lambda包裹确保点击时才启动线程:
hostB = Button(window, text="Host", command=lambda: threading.Thread(target=hostServer).start())
修改后,连接建立时窗口会立即销毁,无需等待socket循环结束。
内容的提问来源于stack exchange,提问作者Noah McBride
相关产品推荐
相关产品推荐

