Python 在Tkinter应用程序旁边运行循环

Python 在Tkinter应用程序旁边运行循环,python,loops,python-2.7,tkinter,Python,Loops,Python 2.7,Tkinter,我是一名高中编程学生,我有一个小问题。我的任务是在Tkinter写一个简单的游戏,一个冰柱从天花板上掉下来,你必须用鼠标避开它。很简单。然而,我遇到了一个问题。每当我在Tkinter应用程序中运行循环时,它都不会打开。我尝试过使用time.sleep()每隔.5秒暂停一次的for循环,循环完成后窗口立即打开。我需要做一些特殊的事情来让循环在Tkinter中工作吗 from Tkinter import * import time import random class App: def

我是一名高中编程学生,我有一个小问题。我的任务是在Tkinter写一个简单的游戏,一个冰柱从天花板上掉下来,你必须用鼠标避开它。很简单。然而,我遇到了一个问题。每当我在Tkinter应用程序中运行循环时,它都不会打开。我尝试过使用time.sleep()每隔.5秒暂停一次的for循环,循环完成后窗口立即打开。我需要做一些特殊的事情来让循环在Tkinter中工作吗

from Tkinter import *
import time
import random

class App:
    def __init__(self, parent):
        self.frame = Frame(root, bg= '#1987DF', width=800, height=800)
        self.frame.bind("<Motion>", self.motionevent)
        self.frame.pack()
        #self.run()
    def randhex(self):
        b = "#"
        for i in range(1, 7):
            a = random.randint(0, 15)
            if a == 10:
                a = "A"
            elif a == 11:
                a = "B"
            elif a == 12:
                a = "C"
            elif a == 13:
                a = "D"
            elif a == 14:
                a = "E"
            elif a == 15:
                a = "F"
            b = b+str(a)
        return b

    def motionevent(self, event):
        xpos, ypos, bg = event.x, event.y, self.randhex()
        str1 = "X : %d  Y : %d BG : %s" % (xpos, ypos, bg)
        root.title(str1)
        x,y, delta = 100, 100, 10
        self.frame.config(bg=bg)

    def run(self):
        for i in range(0, 10):
            time.sleep(.5)
            print 'i'
            self.frame.config(bg=self.randhex())

root = Tk()
app = App(root)
root.mainloop()
从Tkinter导入*
导入时间
随机输入
类应用程序:
定义初始化(自身,父级):
self.frame=frame(根,bg='#1987DF',宽度=800,高度=800)
self.frame.bind(“,self.motionevent)
self.frame.pack()
#self.run()
def randhex(自身):
b=“#”
对于范围(1,7)内的i:
a=random.randint(0,15)
如果a==10:
a=“a”
elif a==11:
a=“B”
elif a==12:
a=“C”
elif a==13:
a=“D”
elif a==14:
a=“E”
elif a==15:
a=“F”
b=b+str(a)
返回b
def motionevent(自我,事件):
xpos,ypos,bg=event.x,event.y,self.randhex()
str1=“X:%d Y:%d BG:%s”%(xpo、ypo、BG)
root.title(str1)
x、 y,δ=10010010
self.frame.config(bg=bg)
def运行(自):
对于范围(0,10)内的i:
时间。睡眠(.5)
打印“我”
self.frame.config(bg=self.randhex())
root=Tk()
app=app(根目录)
root.mainloop()

目前它所要做的就是在鼠标移动时改变背景。当init中显示self.run()的行未注释时,它将打印“i”10次,然后窗口将打开。帮助?

编写基于事件的程序与编写传统程序不同。已经有一个无限循环在运行,与任何无限循环一样,如果在内部放置另一个循环,则在内部循环完成之前,外部循环无法继续。由于外部循环是导致屏幕刷新和事件处理的原因,内部循环有效地冻结了应用程序,直到它们完成为止

因为已经有一个循环在运行,所以不需要创建另一个循环。您只需向事件队列中一次添加一个小作业。实际上,每个作业都是内部循环的一次迭代

例如,如果您想编写这样的内部循环:

for i in range(10):
    print "i:", i
def do_one_iteration(i):
    print "i:", i
    if i < 9:
        root.after_idle(do_one_iteration, i+1)
。。。相反,您应该向事件队列添加一个事件,并且每次事件循环迭代(或者更准确地说,每次它完成处理任何其他事件时),它都会对您的循环进行一次迭代。你是这样做的:

for i in range(10):
    print "i:", i
def do_one_iteration(i):
    print "i:", i
    if i < 9:
        root.after_idle(do_one_iteration, i+1)
def do_one_迭代(i):
打印“i:”,i
如果i<9:
空闲后(做一次迭代,i+1)
然后,在您第一次调用
do_one_iteration
后,它会将自己的下一次迭代放在事件队列中,并继续这样做,直到它决定完成为止

通常,当用户按下按钮(如“开始”按钮)时,您会调用
do\u one\u iteration
。调用它一次,然后它做一点工作(即:将冰柱向下移动几个像素),然后重新安排自己

在游戏开发中,您可能有一个名为
update\u display
的函数,负责重新绘制所有内容。例如,它可以从每个冰柱的Y坐标中减去1。您可以为左右箭头添加绑定以移动播放器(通过增加或减少X坐标),更新函数将使用这些新坐标重新绘制播放器

顺便说一下,您可以使用
after
而不是
after\u idle
在稍有延迟后调用函数,从而降低程序的速度。该延迟可用于控制帧速率。例如,假设更新几乎是即时的(在您的情况下可能是即时的),使用41(毫秒)的参数在之后调用
,会产生大约24 fps的帧速率(24帧乘以41毫秒等于984毫秒,或大约每秒24帧)

这听起来可能很复杂,但只要你做一两次,在实践中就很容易了。

答案可能是: