У меня возникла проблема с работой приложения решетчатых газовых автоматов. Ну, я не могу обновить изображение с помощью функции after(). Приложение запускается и больше ничего не происходит. Я пробовал много комбинаций использования этого метода или любого другого метода для повторения автоматов каждый раз, но безуспешно. Не могли бы вы помочь мне с решением этой проблемы?
Первый файл:
from PIL import Image, ImageTk
import tkinter as tk
import numpy as np
import methods
class Window:
def __init__(self, master):
self.master = master
self.frame = tk.Frame(self.master, background = "white")
self.img_matrix = np.zeros([600, 600, 3], dtype=np.uint8)
self.state_matrix = np.zeros([600, 600, 5], dtype=np.uint8)
self.img_matrix, self.state_matrix = methods.fill_matrix(self.img_matrix, self.state_matrix)
self.img = ImageTk.PhotoImage(image=Image.fromarray(self.img_matrix))
self.canvas = tk.Canvas(self.frame, width=600, height=600)
self.canvas.pack(side = "left", fill = "y")
self.canvas.create_image(0, 0, anchor = "nw", image=self.img)
self.frame.pack()
self.master.after(1000, methods.simulate(self.canvas, self.img_matrix, self.state_matrix))
def main():
root = tk.Tk()
root.withdraw()
top = tk.Toplevel(root)
top.protocol("WM_DELETE_WINDOW", root.destroy)
app = Window(top)
top.title("LGA")
top.mainloop()
if __name__ == '__main__':
main()
и второй:
import numba
from numba import jit, njit
from PIL import Image, ImageTk
import numpy as np
import random
@jit(nopython=True, parallel=True)
def fill_matrix(img_matrix, state_matrix):
for x in numba.prange(0, state_matrix.shape[0]-1):
for y in numba.prange(0, state_matrix.shape[1]-1):
state = state_matrix[x, y]
if y == 0 or x == 0 or y == state_matrix.shape[1]-1 or x == state_matrix.shape[0]-1:
state[0] = 1
state_matrix[x, y] = state
img_matrix[x, y] = [255, 255, 255]
if y == 150 and (0 < x < (((state_matrix.shape[0]-1)/2)-25) or \
(((state_matrix.shape[0]-1)/2)+25 < x < state_matrix.shape[0]-1)):
state[0] = 1
state_matrix[x, y] = state[0]
img_matrix[x, y] = [255, 255, 255]
random_gen_1 = random.randint(0, 100)
treshold = 92
if 0 < y < 150 and 0 < x < (state_matrix.shape[0]-1) and random_gen_1 > treshold:
random_gen_2 = random.randint(1, 4)
if random_gen_2 == 1:
state[1] = 1
elif random_gen_2 == 2:
state[2] = 1
elif random_gen_2 == 3:
state[3] = 1
elif random_gen_2 == 4:
state[4] = 1
state_matrix[x, y] = state
img_matrix[x, y] = [255, 0, 0]
return img_matrix, state_matrix
def simulate(canvas, img_matrix, state_matrix):
new_state_matrix = np.zeros([state_matrix.shape[0], state_matrix.shape[1], 5], dtype=np.uint8)
new_img_matrix = np.zeros([state_matrix.shape[0], state_matrix.shape[1], 3], dtype=np.uint8)
new_state_matrix, new_img_matrix = state_sim(state_matrix, new_state_matrix, img_matrix, new_img_matrix)
img = ImageTk.PhotoImage(image=Image.fromarray(new_img_matrix))
canvas.create_image(0, 0, anchor = "nw", image=img)
#return img, new_img_matrix, new_state_matrix
@jit(nopython=True, parallel=True)
def state_sim(state_matrix, new_state_matrix, img_matrix, new_img_matrix):
for x in numba.prange(0, state_matrix.shape[0]-1):
for y in numba.prange(0, state_matrix.shape[1]-1):
state = state_matrix[x, y]
if state[0] == 1:
new_state_matrix[x, y] = state_matrix[x, y] #[1, 0, 0, 0, 0]
new_img_matrix[x, y] = img_matrix[x, y] #[255, 255, 255]
else:
new_state = state
state_up = state_matrix[x - 1, y]
state_right = state_matrix[x, y + 1]
state_down = state_matrix[x + 1, y]
state_left = state_matrix[x, y - 1]
new_state_up = state_matrix[x - 1, y]
new_state_right = state_matrix[x, y + 1]
new_state_down = state_matrix[x + 1, y]
new_state_left = state_matrix[x, y - 1]
#state
if state_up[3] == 1:
new_state[1] = 1
new_state_up[3] = 0
if state_right[4] == 1:
new_state[2] = 1
new_state_right[4] = 0
if state_down[1] == 1:
new_state[3] = 1
new_state_down[1] = 0
if state_left[2] == 1:
new_state[4] = 1
new_state_left[2] = 0
if new_state[1] == 1 and new_state[3] == 1:
new_state[1] = 0
new_state[2] = 1
new_state[3] = 0
new_state[4] = 1
elif new_state[2] == 1 and new_state[4] == 1:
new_state[1] = 1
new_state[2] = 0
new_state[3] = 1
new_state[4] = 0
new_state_matrix[x, y] = new_state
if new_state[1] == 1 or new_state[2] == 1 or new_state[3] == 1 or new_state[4] == 1:
new_img_matrix[x, y] = [255, 0, 0]
return new_state_matrix, new_img_matrix
Почему функция симуляции() не повторяется каждый раз? Спасибо за ответы!
Чтобы использовать after, вы должны передать ссылку на функцию. Допустим, у меня есть функция hi()
, которая просто выводит «привет» на экран. Если я вызову hi при передаче аргументов after()
, то я передам возвращаемое значение hi()
в качестве параметра: .after(200, hi()) # hi() is equal to None
. Вместо этого я должен передать ссылку так: .after(200, hi)
.
Однако вы не можете этого сделать, потому что вам нужно передать аргументы функции. Для этого вы можете использовать lambda
для создания анонимной функции, которая вызывает вашу со своими параметрами: .after(200, lambda: methods.simulate(self.canvas, self.img_matrix, self.state_matrix))
.
@BryanOakley Я не знал об этом, спасибо, это все еще полезно знать, например, если вы хотите передать аргументы функции, когда вы назначаете ее, например, command=
в кнопке.
Вам не нужно
lambda
передавать позиционные аргументы с помощьюafter
. Это будет работать и будет немного легче читать:self.master.after(1000, methods.simulate, self.canvas, self.img_matrix, self.state_matrix)