Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何在函数调用中间更新TcTimter画布?_Python_Tkinter - Fatal编程技术网

Python 如何在函数调用中间更新TcTimter画布?

Python 如何在函数调用中间更新TcTimter画布?,python,tkinter,Python,Tkinter,我正在用Tkinter编写Conway的生活游戏,我想有一个“Go”按钮,可以让动画开始,并继续自动步进直到结束。我使用画布来绘制环境,但由于“Go”按钮需要在更新画布之前完成函数调用,因此窗口将一直挂起,直到我终止该进程。我曾尝试在我想要更新画布的地方使用canvas.update\u idletasks()和canvas.update()(之后是几秒钟的睡眠),但这似乎没有起到作用。有什么想法吗?下面是我的GameOfLife类,Environment类只是管理单元的“板” from Tki

我正在用Tkinter编写Conway的生活游戏,我想有一个“Go”按钮,可以让动画开始,并继续自动步进直到结束。我使用画布来绘制环境,但由于“Go”按钮需要在更新画布之前完成函数调用,因此窗口将一直挂起,直到我终止该进程。我曾尝试在我想要更新画布的地方使用
canvas.update\u 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()
从Tkinter导入*
从随机导入*
从时间导入时间
从环境导入*
生命类别(对象):
定义初始化(自、主、环境):
self.unitSize=10
self.dimension=envDim*self.unitSize
self.environment=环境(envDim)
self.environment.seedBoard()
self.start=False
帧=帧(主帧)
frame.pack()
按钮(frame,text=“Go”,command=self.Go\u call).pack(side=LEFT)
按钮(frame,text=“Clear”,command=self.reset\u call).pack(side=LEFT)
按钮(frame,text=“Close”,command=frame.quit).pack(side=RIGHT)
canvas=self.drawCanvas(master,self.dimension)
def drawCanvas(自身、主控、尺寸):
self.canvas=canvas(主控,宽度=self.dimension,高度=self.dimension)
self.canvas.pack()
返回自我画布
def go_呼叫(自我):
打印“>”
如果self.environment.started==False:
self.environment.seedBoard()
self.drawState(self.environment)
self.environment.nextBoard()
self.start=True
尽管如此:
self.environment.nextBoard()
self.canvas.delete(全部)
self.drawState(self.environment)
self.canvas.update_idletasks()
睡眠(4)
def重置_呼叫(自):
打印“>”
self.canvas.delete(全部)
self.environment=environment(self.environment.dim)
def drawState(自身、环境):
大小=自身单位大小
对于范围内的x(environment.dim):
对于范围内的y(environment.dim):
如果environment.matrix[x][y].alive==True:
xs=x*大小
ys=y*尺寸
创建_矩形(xs,ys,xs+size,ys+size,fill='black')
envDim=70
root=Tk()
gol=生命的配子(根,环境)
root.mainloop()

您永远不应该在GUI程序中放入无限循环,而且绝对不应该调用sleep。您已经有一个无限循环在运行——事件循环——所以请充分利用它

制作这样的动画的方法是编写一个函数来绘制动画的一帧(或者游戏的回合,选择你的比喻)。然后,让该函数在之后通过
调用自身

大致来说,您的代码应该如下所示:

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)
    ...

如果要添加停止按钮,只需设置一个标志。然后,在
draw
中,只需在调用
self.after

次要建议之前检查标志。似乎您正在删除所有画布对象,并在每次更新状态时创建新的画布对象。在画布上保持相同的矩形,并在每次迭代时更改其填充颜色可能会更有效。为什么
睡眠
4秒钟,不是那么多吗?与问题无关,但像示例代码中那样进行导入确实是个坏主意——除非您确切知道每个模块导出的内容,否则很容易出现名称冲突。根据经验,您永远不应该执行
import*