6

私は Tkinter を使用してコンウェイの人生ゲームを書いています。アニメーションを開始し、終了するまで自動的にステップを続行できる「Go」ボタンが必要です。Canvas を使用して環境を描画していますが、「Go」ボタンはキャンバスを更新する前に関数呼び出しを完了する必要があるため、プロセスを強制終了するまでウィンドウがハングします。キャンバスを更新したいポイントでcanvas.update_idletasks()and (数秒のスリープが続く)を使用しようとしましたが、うまくいかないようです。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()
4

1 に答える 1

8

GUI プログラム内に無限ループを入れてはいけません。決して sleep を呼び出してはいけません。すでに無限ループ (イベント ループ) が実行されているので、それを利用してください。

このようなアニメーションを行う方法は、アニメーションの 1 フレームを描画する関数を作成することです (またはゲームの順番で、比喩を選びます)。次に、その関数が を介して自分自身を呼び出すようにします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)
    ...

停止ボタンを追加する場合は、フラグを設定するだけです。次に、 でdraw、呼び出す前にフラグを確認するだけですself.after

于 2012-06-09T23:57:07.597 に答える