Python Tkinter刷新画布

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python Tkinter刷新画布相关的知识,希望对你有一定的参考价值。

您好我在python中有一个元组,其颜色与通过以下字典在画布中绘制的正方形相关:

colour_mapping = {0: "red", 1: "green", 2: "blue" , 3:"purple"}

更具体地说,例如元组中的节点是:

((2, 3), (3, 3))

这意味着应该以这种方式绘制4个方格:

blue square    purple square
purple square     purple square

然后他们的颜色应该相应地更改为我的元组中的下一个节点

为此,我迭代元组,对于每个元素,我在画布上绘制一个新的矩形,然后我调用time.sleep()函数,以便给用户一些时间来查看与之前状态的差异。我的问题是只有最后一个节点正确呈现而其他所有节点都没有显示。你能帮助我吗?

到目前为止,这是我的代码:

self.parent.title("AlienTiles")
self.style = Style()
self.style.theme_use("default")

self.frame =  Frame(self, relief=RAISED, borderwidth=1)
self.frame.pack(fill=BOTH, expand=1)

self.canvas = Canvas(self.frame)
self.canvas.pack(fill=BOTH, expand=1)

self.pack(fill=BOTH, expand=1)


for i in range(len(path)) : #the tuple is path

            state = path[i].state
            print state
            time.sleep(1)
            y_offset=10
            for x in state:
                start_x=40
                start_y=10
                i=1
                x_offset=0

                for y in x:

                    x0=(start_x*i)+x_offset
                    y0=(start_y*i)+y_offset
                    x1=x0+size
                    y1=y0+size
                    colour=colour_mapping[y]

                    print colour

                    self.canvas.create_rectangle(x0, y0, x1, y1, fill=colour)
                    x_offset=x_offset+size+10


                y_offset=y_offset+size+10

总而言之,我尝试制作上述动画。有什么我不正确的想法或在每个循环刷新画布的东西?

答案

画布刷新的唯一方法是为事件循环提供服务“重绘”事件。在你的循环中,你永远不会给事件循环提供更新的机会,所以你没有看到任何变化。

快速解决方法是调用self.canvas.update_idletasks,但这只是一个黑客而不是一个合适的解决方案。

做动画的正确方法是使用事件循环来进行迭代。您可以通过将要完成的工作放在队列上来完成此操作 - 在本例中为空闲事件队列。您可以使用after命令将事物放在此队列中。

你应该做的是编写一个函数,对你的动画进行一次迭代。基本上,将while循环中的所有内容都移到函数中。然后,只要有工作要做,就安排不断调用该功能。您可以在该函数中调用after,也可以使用单独的函数控制动画。

粗略地说,解决方案看起来像这样:

def do_one_frame(self, ...):
    # do whatever you need to draw one frame

    if (there_is_more_work_to_be_done):
        self.after(10, do_one_frame)

这将绘制动画的一帧,检查是否有任何新帧要绘制,然后安排在10ms内绘制下一帧。当然,您可以将该值设置为您想要的任何值,以便控制动画的速度。

本网站上有这种技术的工作示例。例如,请参阅https://stackoverflow.com/a/25431690/7432

另一答案

首先,我有点困惑为什么((2,3)(3,3))会得到绿色和蓝色方块。你的颜色编码似乎表明它们会是蓝色和紫色,不是吗?

其次,我不完全确定我理解这句话“然后他们的颜色应该根据我元组中的下一个节点进行更改”。这是否意味着你将传入((2,3)(3,3))并期望获得4个方格,然后下一次传入((2,3)(3,3)(1) ,2))你会期望6个方块用蓝色绘制?

第三,你的计划的输出是什么?看起来好像你有足够的打印语句,你应该能够找出问题所在。

在没有完全理解程序的情况下进行猜测,我猜测问题是你的一个for循环没有迭代正确的值,这导致不是所有的正方形被绘制。我的猜测是第一个:

for i in range(len(path)) :

但这是一个猜测,因为就像我说的那样,我并不完全了解发生了什么。如果你能回答我的一些问题,我会尽力帮助你。对不起,我没有更多的帮助。

以上是关于Python Tkinter刷新画布的主要内容,如果未能解决你的问题,请参考以下文章

Python Tkinter。以画布形式打开 BMP 文件

Python 中 Tkinter 画布上 .jpg 图像的滚动条

如何使用 PYTHON 的“tkinter”模块在画布上显示图像,特别适用于 linux?

Python Tkinter - 保存画布 - tkinter 崩溃

Python,Tkinter:如何在可滚动画布上获取坐标

Python中使用tkinter创建透明图层不规则组件插入GIF动图等功能实现