首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在tkinter中重复创建和删除对象(例如矩形)的时间延迟

在tkinter中重复创建和删除对象(例如矩形)的时间延迟
EN

Stack Overflow用户
提问于 2020-02-07 14:57:27
回答 2查看 536关注 0票数 0

我对蟒蛇很陌生。目前,我的目标是编写一个程序,该程序必须在几秒钟的对象(矩形、圆圈等).If后反复创建和删除,我在一个单独的函数中使用.after方法,得到一个错误: UnboundLocalError:在assignmentWhen之前引用的局部变量“计数器”,查看我自己的代码。或者,如果我把重复的代码放在程序的主要部分,它只显示最后一个状态,而不是在两者之间的状态(请参阅代码中“”和“”之间的描述。我在网上搜索了一段时间,但我无法独享它。我希望你能帮助我。

下面是我的代码的一个简化版本(实际上,我正在处理一个rec的列表),它显示了我的问题:

代码语言:javascript
复制
import tkinter as tk


def master_field(text):
    """ work field (master) construction"""
    master.geometry('500x500+0+0') 
    master.title(text) 

def stop_button():
    """exit"""
    b = tk.Button(master, text = 'Exit', width=2, command = master.destroy)
    b.place(x = 50, y = 0, width = 100)

def built_canvas():
    """create a canvas"""
    canvas=tk.Canvas(master, width = canvas_width, height = canvas_height, borderwidth = 1, bg='light grey', highlightthickness=0, highlightbackground="blue")
    canvas.place(x = 0, y = 20)
    return canvas

def update_canvas():

    while counter<10:
        canvas.delete(rec)
        rec = canvas.create_rectangle(x1+i*10,y1+i*10,x2+i*10,y2+i*10, width=0, fill="green")
        counter +=1
        master.after(500,update_canvas)


# MAIN
master = tk.Tk()
master_field('MY FIELD')
stop_button()

canvas_width = 200
canvas_height = 200
canvas = built_canvas()

cell_width = 10
x1 = 10
y1 = 10
x2 = x1+10
y2 = y1+10
rec = canvas.create_rectangle(x1,y1,x2,y2, width=0, fill="green")

counter = 0
master.after(500,update_canvas)

"""
# The code below only gives the final state

for i in range(1,10):
    master.after(500)
    canvas.delete(rec)
    rec = canvas.create_rectangle(x1+i*10,y1+i*10,x2+i*10,y2+i*10, width=0, fill="green")
"""
master.mainloop()
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-02-07 16:24:12

tkinter函数after做两件非常不同的事情--如果您在“之间的部分中这样称呼它:

master.after(500)

这使得您的python程序等待半秒钟,然后继续。

如果你像你在update_canvas中的循环那样调用它

master.after(500, update_canvas)

然后,它立即返回,没有等待,但计划update_canvas在未来的半秒内发生。

所以上面的版本

代码语言:javascript
复制
 while counter<10:
     canvas.delete(rec)
     rec = canvas.create_rectangle(x1+i*10,y1+i*10,x2+i*10,y2+i*10, width=0, fill="green")
     counter +=1
     master.after(500,update_canvas)

没有给出正确的时间延迟,因为循环在没有等待的情况下运行了所有10个迭代,并且调度update_canvas发生10次,所有的时间都是从现在开始的半秒之后,而不是彼此之间的半秒。

引号中的版本:

代码语言:javascript
复制
for i in range(1,10):
    master.after(500)
    canvas.delete(rec)
    rec = canvas.create_rectangle(x1+i*10,y1+i*10,x2+i*10,y2+i*10, width=0, fill="green")

有一个不同的问题--这会多次运行循环,每次等待半秒,但是由于尚未到达master.mainloop(),窗口甚至不可见--所以它可以动画对象,但您还不能看到它。

要解决这个问题,您需要使用将来调度的第一个版本,这样您就可以调度它,然后调用mainloop(),然后有第一个调度,下一个调度。

如果我们这样做的话:

代码语言:javascript
复制
def update_canvas():
    global counter, rec # global lets you change counter and rec from inside the function - avoids 'Unbound local variable'
    if counter >= 10:
        return #  If the counter is big enough, stop and do nothing more
    else:
        canvas.delete(rec) # Update the rectangle
        i = counter
        rec = canvas.create_rectangle(x1+i*10,y1+i*10,x2+i*10,y2+i*10, width=0, fill="green")
        counter +=1 # Add to the counter so we don't animate forever
        master.after(500,update_canvas) # Schedule the next update for half a second in the future

然后它应该使广场生动活泼。这样循环就没有了,但是当我们第一次调用update_canvas时,update_canvas函数本身要求tkinter稍后再调用它。最终,计数器变得足够大,它不再要求另一个电话和动画停止。

票数 2
EN

Stack Overflow用户

发布于 2020-02-08 05:42:23

您不需要update_canvas()中的while循环。此外,您不需要重新创建矩形,只需移动它:

代码语言:javascript
复制
def update_canvas(counter=0):
    if counter < 10:
        canvas.move(rec, 10, 10)
        master.after(500, update_canvas, counter+1)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60115888

复制
相关文章

相似问题

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