我正在使用Tkinter编写Conway的生活游戏,我希望有一个"Go"按钮,允许动画开始,并继续自动步进直到终止.我正在使用Canvas来绘制环境,但由于"Go"按钮需要在更新画布之前完成函数调用,因此窗口会挂起,直到我终止该进程.我试图在我想要更新画布的地方使用canvas.update_idletasks()和canvas.update()(后面几秒钟的睡眠),但这似乎没有办法.有任何想法吗?下面是我的GameOfLife类,Environment类只管理单元格的"板".
from Tkinter import *
from random import *
from time import time
from Environment import *
class GameOfLife(object):
def __init__(self, master, envDim):
self.unitSize = 10
self.dimension = envDim * self.unitSize
self.environment = Environment(envDim)
self.environment.seedBoard()
self.started = False
frame = Frame(master)
frame.pack()
Button(frame, text = "Go", command = self.go_call).pack(side = LEFT)
Button(frame, text = "Clear", command = self.reset_call).pack(side = LEFT)
Button(frame, text = "Close", command = frame.quit).pack(side = RIGHT)
canvas = self.drawCanvas(master, self.dimension)
def drawCanvas(self, master, dimension):
self.canvas = Canvas(master, width = self.dimension, height = self.dimension)
self.canvas.pack()
return self.canvas
def go_call(self):
print "<< Go Call >>"
if self.environment.started == False:
self.environment.seedBoard()
self.drawState(self.environment)
self.environment.nextBoard()
self.started = True
while True:
self.environment.nextBoard()
self.canvas.delete(ALL)
self.drawState(self.environment)
self.canvas.update_idletasks()
sleep(4)
def reset_call(self):
print "<< Reset Call >>"
self.canvas.delete(ALL)
self.environment = Environment(self.environment.dim)
def drawState(self, environment):
size = self.unitSize
for x in range(environment.dim):
for y in range(environment.dim):
if environment.matrix[x][y].alive == True:
xs = x * size
ys = y * size
self.canvas.create_rectangle(xs, ys, xs+size, ys+size, fill = 'black')
envDim = 70
root = Tk()
gol = GameOfLife(root, envDim)
root.mainloop()
Run Code Online (Sandbox Code Playgroud)
你永远不应该在你的GUI程序中放置一个无限循环,你绝对不应该称之为睡眠.你已经有一个无限循环运行 - 事件循环 - 所以利用它.
像这样做动画的方法是编写一个绘制动画的一帧(或者转动游戏,选择你的比喻)的函数.然后,让该函数通过自己调用after.
粗略地说,您的代码应如下所示:
def draw(self):
# draw the board according to the current state
...
# arrange for the next frame to draw in 4 seconds
self.after(4000, self.draw)
def __init__(self, ...):
...
self.go = tk.Button(self, text="Go", command=self.draw)
...
Run Code Online (Sandbox Code Playgroud)
如果要添加停止按钮,只需设置一个标志即可.然后,在draw调用之前,只需检查标志self.after
| 归档时间: |
|
| 查看次数: |
13722 次 |
| 最近记录: |