如何在Tkinter mainloop()中实现函数的无限循环调用?
解决Tkinter中康威生命游戏自动循环的问题
嘿,我瞅了你的代码,问题主要出在after方法的使用方式和play函数的循环逻辑上,咱们一步步搞定它:
1. 先修复after的调用错误
你主程序里写的这行:
root.after(1000, conway.play())
犯了个典型的Tkinter错误——你直接执行了conway.play(),把函数的返回值(这里是None)传给了after,但after需要的是函数本身的引用,这样它才能在指定时间后帮你调用这个函数。
把这行改成:
root.after(1000, conway.play)
2. 让play函数自己触发循环
现在你的play函数只执行一次就结束了,要实现自动迭代,得让它在执行完后,主动安排下一次调用,结合is_running状态来控制循环:
def play(self): # Calculates and sets the next generation. Intended to be used in a loop if self.is_running: self.apply_ruleset() self.matrix.count_neighbours() self.apply_colors() # 每隔1秒调用一次自己,形成持续循环 self.master.after(1000, self.play)
这样只要is_running是True,play就会反复被调用,实现自动更新。
3. 额外修复:规则计算的逻辑bug
顺便提个重要的问题:你当前的apply_ruleset在遍历细胞时直接修改存活状态,这会导致后续细胞计算邻居时用的是已经被修改过的状态,规则执行会完全出错(相当于边计算边修改当前代的状态,而不是基于完整的当前代计算下一代)。
正确的做法是先把所有细胞的下一代状态计算好,存在临时矩阵里,然后统一更新:
def apply_ruleset(self): # Fixed the state update bug in Conway's rules size = len(self.matrix.cells) # 创建临时矩阵存储下一代的存活状态 next_gen = [[False for _ in range(size)] for _ in range(size)] for x in range(size): for y in range(size): current_cell = self.cell(x,y) is_alive = current_cell.is_alive() neighbour_count = current_cell.neighbours # 应用康威生命游戏规则 if is_alive: # 存活细胞:邻居数为2或3时继续存活,否则死亡 next_gen[x][y] = 2 <= neighbour_count <= 3 else: # 死亡细胞:邻居数恰好为3时复活 next_gen[x][y] = neighbour_count == 3 # 统一更新所有细胞的状态 for x in range(size): for y in range(size): current_cell = self.cell(x,y) if next_gen[x][y] != current_cell.is_alive(): current_cell.toggle()
最后测试
把这些修改完成后,点击play按钮切换is_running状态,就能控制自动循环的启停了,手动的next按钮也能正常工作。
内容的提问来源于stack exchange,提问作者The Fool
相关产品推荐
相关产品推荐

