python - Tkinter .after 方法卡住窗口?

标签 python sockets events tkinter

我有一个简单的聊天客户端,我试图使用 Tkinter 作为界面。我的问题是,当使用 .after 为聊天输入/输出运行 mainloop 时,窗口卡住并阻塞,直到收到另一条消息。

class Client(Frame):

    def __init__(self, **kwargs):
        Frame.__init__(self, Tk())
        self.pack()

        self.lb = Listbox(self, width=100, height=30)
        self.lb.pack()

        self.show_data = self.lb.after(1000, self.chat_handle)

        self.entry = Entry(self)
        self.entry.bind('<Return>', self.input_handle)
        self.entry.pack(side=BOTTOM, fill=X)

    def input_handle(self, event):
        msg = self.entry.get()
        self.entry.delete(0, 'end')
        new_msg = 'privmsg %s :' % self.channel + msg + '\r\n'
        self.client.sendall(new_msg)
        self.lb.insert(END, self.nick + ' | ' + msg)

    def chat_handle(self):
        try:
            self.data = self.client.recvfrom(1024)
        except socket.error:
            self.lb.insert(END, "Bad Connection!")
            return
        if self.data and len(self.data[0]) > 0:
            self.lb.insert(END, self.data[0])
        elif self.data and len(self.data[0]) == 0:
            self.lb.insert(END, "Connection Dropped!")
            return
        self.show_data = self.lb.after(1000, self.chat_handle)

此代码块已缩短,但显示了所涉及的相关部分。 Entry 小部件将在 .after 被调用时长时间无响应,并且在收到消息之前不会响应。

Entry 小部件再次响应时,输入字段包含输入的所有数据,但在“卡住”期间我看不到更改。 Listbox 小部件也是如此。

如果有人能阐明为什么会这样,或者指出我是否没有在这里使用某种方法,我们将不胜感激。

编辑:经过更多研究,它看起来像 socket 数据在调用时阻塞,并且窗口在此期间被卡住。

最佳答案

after 在给定时间后执行回调函数;然而,这个方法也在主线程中运行。因此,如果有一个操作比平时花费更多的时间(在这种情况下,阻塞 recvfrom),GUI 将无响应,直到执行完整的回调。

为了解决这个问题,一个常见的方法是生成一个新线程,并使用类似 Queue 的同步对象与您的 Tkinter 代码进行通信。 .因此,当您从套接字接收到数据时,您将其放入队列中,然后在 after 回调内的主线程中定期检查。

这个问题的答案可以采用相同的方法:Tkinter: How to use threads to preventing main event loop from "freezing"

关于python - Tkinter .after 方法卡住窗口?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17015741/

相关文章:

sockets - 当 boost.asio 流上有一些数据需要读取而不将其读入缓冲区时,如何获得回调?

当客户端断开连接时,C 服务器停止响应

javascript - Adobe Edge 如何通过代码禁用自动播放?

javascript - 为什么 jQuery 事件没有被触发?

Python tkinter TreeView 列大小

python - 如何创建嵌套字典,以便通过Python为Elasticsearch创建映射?

python - 从python内存中的MPEG(.ts)文件中提取音频,而不将MPEG写入文件

python - Pandas - 从具有出现次数的可迭代对象中获取虚拟对象

c - Telnet 客户端及其对 EOL 的处理

java - 如何从可编辑组合框中更改的文本获取事件?