您好我在python中编写了一个wireworld。我目前正致力于动画\ GUI并面临一些问题。几秒钟后动画会变慢。 我对编程很新,对python和OOP也很陌生,所以我可以接受建议和意见,但我的具体问题是我无法弄清楚错误是什么用我的代码,它需要50%的CPU来显示改变颜色的小方块...
如果有人可以帮助我,那就太好了。
这是我的代码:
import Tkinter as tk
import random as rd
class Universe(object):
def __init__(self, width, height):
self.width = width
self.height = height
self.cells = dict()
for i in range(0, height):
for j in range(0, width):
self.cells[(i, j)] = Cell((i, j), 0, width, height)
def generate_random(self):
for current_cell in self.cells:
self.cells[current_cell].state = rd.randint(0, 3)
def apply_rules(self):
next_state = dict()
for current_cell in self.cells:
if self.cells[current_cell].state == 3:
if self.cells[current_cell].count_electron_heads(self) == 1:
next_state[current_cell] = 1
elif self.cells[current_cell].count_electron_heads(self) == 2:
next_state[current_cell] = 1
else:
next_state[current_cell] = 3
elif self.cells[current_cell].state == 2:
next_state[current_cell] = 3
elif self.cells[current_cell].state == 1:
next_state[current_cell] = 2
else:
next_state[current_cell] = 0
for current_cell in next_state:
self.cells[current_cell].state = next_state[current_cell]
def plain_text_display(self):
for i in range(0, self.height):
row = list()
for j in range(0, self.width):
row.append(self.cells[(i, j)].state)
print(row)
class Cell(object):
def __init__(self, coordinates, state, universe_width, universe_height):
self.state = state
self.coordinates = coordinates
self.neighborhood = [[self.coordinates[0] - 1, self.coordinates[1] - 1],
[self.coordinates[0] - 1, self.coordinates[1]],
[self.coordinates[0] - 1, self.coordinates[1] + 1],
[self.coordinates[0], self.coordinates[1] - 1],
[self.coordinates[0], self.coordinates[1] + 1],
[self.coordinates[0] + 1, self.coordinates[1] - 1],
[self.coordinates[0] + 1, self.coordinates[1]],
[self.coordinates[0] + 1, self.coordinates[1] + 1]]
for i in range(0, len(self.neighborhood)):
if self.neighborhood[i][0] < 0:
self.neighborhood[i][0] = universe_height - 1
elif self.neighborhood[i][0] > universe_height - 1:
self.neighborhood[i][0] = 0
if self.neighborhood[i][1] < 0:
self.neighborhood[i][1] = universe_width - 1
elif self.neighborhood[i][1] > universe_width - 1:
self.neighborhood[i][1] = 0
def count_electron_heads(self, universe):
electron_heads_count = 0
for neighbor_cell_coordinates in self.neighborhood:
if universe.cells[(neighbor_cell_coordinates[0], neighbor_cell_coordinates[1])].state == 1:
electron_heads_count += 1
return electron_heads_count
class GUI(tk.Tk):
def __init__(self, universe):
tk.Tk.__init__(self)
self.cell_size = 12
self.ui_frame = tk.Frame(self, width=self.cell_size*universe.width, height=60, bg="#282729")
self.ui_frame.pack(fill="x", expand=True)
self.cell_canvas = tk.Canvas(self, width=self.cell_size*universe.width, height=self.cell_size*universe.height,
borderwidth=0, highlightthickness=0)
self.cell_canvas.pack(fill="both", expand=True)
self.cells = dict()
for i in range(0, universe.height):
for j in range(0, universe.width):
if universe.cells[(i, j)].state == 1:
color = "#0099FF"
elif universe.cells[(i, j)].state == 2:
color = "#CCFFFF"
elif universe.cells[(i, j)].state == 3:
color = "#EDBE02"
else:
color = "#0C1010"
self.cells[(i, j)] = self.cell_canvas.create_rectangle(j*self.cell_size, i*self.cell_size,
(j+1)*self.cell_size, (i+1)*self.cell_size,
fill=color, tag=universe.cells[(i, j)])
self.draw_button = tk.Button(self.ui_frame, text="Draw", command=lambda: self.draw(universe))
self.draw_button.pack(side="left")
def draw(self, universe):
for i in range(0, universe.height):
for j in range(0, universe.width):
if universe.cells[(i, j)].state == 1:
color = "#0099FF"
elif universe.cells[(i, j)].state == 2:
color = "#CCFFFF"
elif universe.cells[(i, j)].state == 3:
color = "#EDBE02"
else:
color = "#0C1010"
self.cells[(i, j)] = self.cell_canvas.create_rectangle(j*self.cell_size, i*self.cell_size,
(j+1)*self.cell_size, (i+1)*self.cell_size,
fill=color, tag=universe.cells[(i, j)])
universe.apply_rules()
self.after(200, lambda: self.draw(universe))
wireworld = Universe(20, 20)
wireworld.generate_random()
g = GUI(wireworld)
g.mainloop()
答案 0 :(得分:1)
问题是,你每200毫秒在画布上创建新的400个矩形。仅仅10秒钟就有20,000个矩形。一旦你开始进入成千上万的对象,画布将开始减速。一旦你有超过几十万,它将开始变得非常猛烈。你将在不到一分钟的时间内完成100,000件物品。
您需要调整算法以仅创建一次所有矩形。之后,您只需使用itemconfig
方法调整颜色。假设您只想用动画的每一帧更改颜色,请在方法draw
中替换用于创建矩形的代码:
self.cell_canvas.itemconfig(self.cells[(i,j)], fill=color)