首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Tkinter的奇怪函数行为

Tkinter的奇怪函数行为
EN

Stack Overflow用户
提问于 2012-12-10 13:03:41
回答 1查看 239关注 0票数 2

我们在事件回调中有一些代码,如下所示:

代码语言:javascript
复制
...
self.position.side = -self.position.side
self.update_with_board() # displays self.position graphically
ai_move = self.brain.get_move(self.position)
...

update()被立即调用,但直到ai_move行才会影响图形用户界面。

然而,当我这样做的时候:

代码语言:javascript
复制
...
self.position.side = -self.position.side
self.update_with_board() # displays self.position graphically
raw_input()
ai_move = self.brain.get_move(self.position)
...

当它请求输入时,它会立即以图形方式更新。我不知道这是怎么回事:也许是时髦的懒惰的评估,或者是我不知道的tkinter计划?如何让GUI按指定的顺序而不是延迟更新?

编辑:对不起,我没有使用内置的update()方法,而是我定义来绘制的方法。我将其重命名为update_with_board(),并看到了相同的行为。

代码语言:javascript
复制
def update_with_board(self):
    for i in range(8):
        for j in range(8):
            color = "gray" if (i+j) % 2 else "white"
            self.canvas.create_rectangle(self.square * i, self.square * j, self.square * (i+1), self.square * (j+1), fill=color)
            if self.position.board[8 * j + i] in self.ims.keys():
                self.canvas.create_image(self.square * i + self.square/2,
                self.square * j + self.square/2, image = self.ims[self.position.board[8 * j + i]])  
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-12-10 13:39:01

再做一些研究,我很确定我的评论是正确的。

每次通过事件循环,UI都会根据需要更新所有小部件。调用update基本上只是强制它现在运行事件循环。因此,如果您正在进行事件回调,您将递归地进入事件循环,这是一件非常糟糕的事情,并且可能导致无限递归。

正如The TkInter Book所说,update

处理所有挂起的事件,调用事件回调,完成任何挂起的几何图形管理,根据需要重新绘制小部件,并调用所有挂起的空闲任务。应该小心使用此方法,因为如果从错误的位置调用(例如,从事件回调中调用,或者从可以以任何方式从事件回调调用的函数等),它可能会导致非常糟糕的竞争条件。如果不确定,请改用update_idletasks。

同样,the TkInter reference说:

此方法强制更新显示。只有当您知道自己在做什么时才应该使用它,因为它可能导致不可预测的行为或循环。它永远不应该从事件回调或从事件回调调用的函数中调用。

经过测试,似乎至少在某些情况下,当您从事件循环内部调用update时,TkInter会忽略您。大概是为了防止无限递归,但我还没有查看代码来验证这一点。

无论如何,这不是您想要的函数,所以它为什么没有做文档中没有记录的事情并不重要。

如果您需要在事件回调中触发更新,请调用update_idletasks。这实际上调用了所有挂起的“空闲”任务,包括重绘,而不调用任何事件回调。(不是“下次我们在事件循环中没有其他事情要做的时候更新”)。

同时,在事件回调中调用raw_input更糟糕。你阻塞了终端输入上的主事件循环。除非这仅仅是您为了调试而做的事情,否则这是一个非常糟糕的想法。即使是为了调试的目的,测试它也是一件非常奇怪的事情,而且无论发生什么都与正常行为无关,这是完全合理的。

有关更多背景信息,请参阅本网站上的问题TkInter: How do widgets update或搜索update_idletasks,或者查看右侧的一些相关链接(至少有两个相关链接)。

根据您的编辑,事实证明,您似乎遇到了相反的问题-您只是更改了一些东西,而没有告诉TkInter对它做任何事情,所以这些更改直到下一次通过事件循环才会显示出来(这意味着直到您从这个函数返回之后)。但答案基本上是一样的--一种方式是“用update_idletasks替换你对update的调用”,另一种方式是“添加对update_idletasks的调用”。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13795265

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档