当前位置: 首页 > 知识库问答 >
问题:

后方法冻结窗口?

满增
2023-03-14

我有一个简单的聊天客户端,我正试图使用Tkinter作为界面。我的问题是,使用运行main循环。在进行聊天输入/输出后,窗口将冻结并阻塞,直到收到另一条消息。

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小部件将在很长一段时间内变得无响应,而。在被调用之后,直到收到消息才会响应。

条目小部件再次响应时,条目字段包含输入的所有数据,但在“冻结”时间内我看不到更改。列表框小部件也是如此。

如果有人能解释一下为什么会这样,或者指出我是否错过了这里使用的方法,那将是非常感激的。

编辑:经过进一步的研究,它看起来像是每当调用它时,socket数据就被阻塞了,在这段时间内窗口被冻结了。

共有2个答案

谯德佑
2023-03-14

我学习了如何使用select进行系统调用,以检查套接字文件是否已准备好读取。

如何设置超时Python的套接字recv方法?

class Client(Frame):

    def __init__(self, **kwargs):
        self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.client.connect(("host", port))
        self.client.setblocking(0)
        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):
        socket_data = select.select([self.client], [], [], 0.3) # set timeout on last arg
        if socket_data[0]:
            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_hand
公西毅
2023-03-14

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

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

这是一个问题,其答案可以调整为使用相同的方法: Tkinter:如何使用线程来防止主事件循环“冻结”

 类似资料:
  • 如有任何帮助,我们将不胜感激。 问候你,Surender

  • 我在Pycharm有一个简单的项目,我正在努力加载到VPS上。我想利用pip冻结来构建需求。txt文件,并在VPS上安装所需的软件包。 不幸的是,当我激活与我的项目关联的 venv 时,pip freeze 的输出似乎是我默认 python3 安装中的所有包,而不是我的项目。 我上传了一张屏幕截图,显示了Python解释器设置和终端pip冻结输出。 在这种情况下,venv应该只包含pip、sele

  • 我使用甲骨文表格10g。它是基于web的甲骨文表单应用程序。我想从Oracle窗体10g生成Excel报表。我配置了WEBUTIL并使用CLIENT_OLE2包。在触发器WHEN-BUTTON-PRESSED中声明的过程。当按下按钮时,突然表单冻结,他们什么也做不了。退出按钮和菜单选项停止工作。它不提供任何信息,也不做任何操作。 程序代码:

  • 问题内容: public class Main extends JFrame{ 这是主类,这是它调用的框架类。 主类调用框架类..它需要保持一段时间,然后再移到另一个框架..但是发生的是主类调用它,该框架出现了,但是其中没有内容。显示,然后移至frame1()// 但是如果我像 新的Frame(); 然后按住,显示内容,然后移动。 那么为什么在Main()调用Frame()时它不起作用? 甚至这段

  • 我正在为一个班做一个基本的乒乓球游戏。我让Pong工作,启动时有一个GUI显示,不幸的是,我似乎无法从开始按钮启动游戏。我已经在代码上注释了问题所在,并删除了不相关的代码。 有什么想法吗?

  • 本文向大家介绍Javascript刷新窗口方法小结,包括了Javascript刷新窗口方法小结的使用技巧和注意事项,需要的朋友参考一下 本文实例总结了Javascript刷新窗口方法。分享给大家供大家参考,具体如下: 1.javascript 刷新父窗口 2.javascript 刷新本窗口 3.javascript 刷新本窗口(新) 4.javascript 刷新本窗口并追加一个参数 希望本文所