Python 在Tkinter中随时间更改GUI

Python 在Tkinter中随时间更改GUI,python,python-2.7,graphics,tkinter,conways-game-of-life,Python,Python 2.7,Graphics,Tkinter,Conways Game Of Life,我正在用Tkinter在{ython}中构建一个康威的生命图形游戏。游戏逻辑和其他一切都很好,我只是停留在代码的最后一部分,即使在阅读了库之后也无法理解 self.after(1000,self.draw(bigThing)) 以下是完整的代码: from Tkinter import * from button import * import numpy import test1 import time class AppFrame(Frame): def __init__(self,

我正在用Tkinter在{ython}中构建一个康威的生命图形游戏。游戏逻辑和其他一切都很好,我只是停留在代码的最后一部分,即使在阅读了库之后也无法理解

self.after(1000,self.draw(bigThing))
以下是完整的代码:

from Tkinter import *
from button import *
import numpy
import test1
import time

class AppFrame(Frame):


def __init__(self,root, buttonlist):
    Frame.__init__(self, root, relief='sunken', width=600, height=600)
    self.gameisrunning = False
    self.buttonlist = buttonlist
    self.root = root

    self.w = Canvas(self,width = 505, height =505)


    self.boulis = []
    for k in range(1,101):
        for i in range(1, 101):

            button = Buttons(self.w, i * 5, k * 5, i * 5 + 5, k * 5 + 5,k ,i,buttonlist)
            self.boulis.append(button)


    self.whole = list(self.chunks(self.boulis, 100))

    self.grid(column =0, columnspan = 4)
    self.w.grid(column = 0)

    clear = Button(self.root,text = "clear")
    clear.grid(column = 0, row = 1)
    self.run = Button(self.root,text = "run", command = self.runit)
    self.run.grid(column = 3, row = 1)
    self.root.mainloop()

def runit(self):

    if self.gameisrunning == False:
        self.gameisrunning = True
        self.transformer = self.buttonlist
        while self.gameisrunning == True:
            bigThing = test1.theNextBigThing(self.transformer)
            self.transformer = bigThing
            self.root.after(1000,self.draw, bigThing)


    elif self.gameisrunning == True:
        self.gameisrunning = False


def draw (self, board):
    for k in range (0, 100):
        for i in range (0, 100):
            if board[k + 1][i + 1] == 1:
                self.whole[k][i].activate()
            elif board[k + 1][i + 1] == 0:
                self.whole[k][i].deactivate()

def chunks(self,l, n):
    """ Yield successive n-sized chunks from l.
    """
    for i in xrange(0, len(l), n):
        yield l[i:i+n]
我稍微改变了一下结构。“runit”方法下我想画的任何东西似乎都不起作用。我不知道为什么会发生这种情况。“runit”中的所有其他函数都工作得很好。只有这个不起作用:

self.root.after(1000,self.draw(bigThing))
这是我的按钮类:

##button.py
from Tkinter import *


class Buttons:

def __init__(self,canvas,bx,by,tx,ty, k, i,buttonlist):
    self.buttonlist = buttonlist
    self.canvas = canvas
    self.rec = canvas.create_rectangle((bx,by,tx,ty),fill = "lightgray",
                                       activefill= 'black', outline = 'lightgray')
    self.canvas.tag_bind(self.rec, "<Button-1>", lambda event: self.callback())
    self.active = False

    self.k = k
    self.i = i

    self.xmin = bx
    self.xmax = tx
    self.ymin = by
    self.ymax = ty
    ##print (bx, by, tx, ty)

def activate(self):
    self.canvas.itemconfigure(self.rec, fill = 'black')

def deactivate(self):
    self.canvas.itemconfig(self.rec, fill='lightgray')

def callback(self):
    self.activate()
    self.buttonlist[self.k][self.i] = 1
##button.py
从Tkinter进口*
类别按钮:
定义初始化(self、canvas、bx、by、tx、ty、k、i、buttonlist):
self.buttonlist=按钮列表
self.canvas=画布
self.rec=canvas.create_矩形((bx,by,tx,ty),fill=“lightgray”,
activefill='黑色',outline='浅灰色')
self.canvas.tag_bind(self.rec,“,lambda事件:self.callback())
self.active=False
self.k=k
self.i=i
self.xmin=bx
self.xmax=tx
self.ymin=by
self.ymax=ty
##打印(bx、by、tx、ty)
def激活(自):
self.canvas.itemconfigure(self.rec,fill='black')
def停用(自我):
self.canvas.itemconfig(self.rec,fill='lightgray')
def回调(自):
self.activate()
self.buttonlist[self.k][self.i]=1

由于您的
AppFrame,您得到了这个错误。\uuu init\uuu
不调用
Frame
超构造函数--
AppFrame
对象因此不是一个合适的
Tk
对象。该方法中的代码似乎与应该调用它的代码以及其中声明的
Frame
组合在一起(
self.f
)实际上应该是
self

class AppFrame(Frame):
    def __init__(self, root, buttonlist):
        Frame.__init__(self, root, relief='sunken', width=600, height=600)
        self.root = root
        self.gameisrunning = False
        self.w = Canvas(self.f, width = 505, height =505)

        # [as before, but with self instead of self.f]
通常,在特定于应用程序的框架之外构建
root
对象的模块化程度更高(这使您可以将应用程序嵌入根目录以外的内容):


那么为什么我们要调用框架超级构造函数呢?框架不是TK对象的一部分吗?谢谢你。如果你不调用超级构造函数,
AppFrame
实例实际上不是一个合适的
Frame
实例,因此就没有TK方法和属性(如本例中的
TK
属性)。我按您所说的更改了结构,错误消失了,但绘图仍然不起作用。
f()
立即调用
f
函数。如果您想在一秒钟内绘制大对象,请在
之后更改
调用:
self.root.after(1000,self.draw,bigThing)
但是动画仍然没有显示,是因为我们不能在主循环之后更改图形?还是因为while循环?有几个错误。我已经指出了明显的错误。是的,你不应该在GUI线程中使用阻塞while循环。另外,不要在
\uu init\uuuuuuuu()中调用
mainloop()
@J.F.Sebastian我不知道如何与GUI对话。以前,while循环在GUI之外,但它甚至没有在“main loop”之后调用“while”循环。你能更具体地谈谈如何将它移到外面以及它是如何工作的吗?我真的很感激。这取决于
test1.theNextBigThing()
阻塞,如果阻塞,那么它是I/O还是CPU受限。如果它不阻塞,那么只需使用
self.after()
运行循环体。如果它阻塞,但不使用可能占用GIL太长时间的C扩展,那么您可以使用后台线程来运行它和
队列()
要在线程之间交换项目,
def main():
    root = Tk()
    root.geometry = "1000x1000"
    buttonlist = ... # needs to be filled in
    app = AppFrame(root, buttonlist)

    # ...