Home > Software engineering >  Tkinter: update window every n computed configurations
Tkinter: update window every n computed configurations

Time:11-09

I'm doing a simulation where each call of the main algorithm (which keeps computing until stop button is pressed) updates a matrix. One step takes 10ms but the refresh rate of my screen (60Hz) is less than the 100Hz needed to update the canvas in real time. Thus I would like to update the canvas every n (e.g. 3) computed configurations so that waiting for the drawing doesn't slow down the computation.

However in my main algorithm computing and drawing are coupled together, and I'm wondering how to decouple these actions. Here is my pseudocode for now:

def compute():
   if running:
      #here we compute how to update the matrix ...
      pixel(matrix) #...and the corresponding pixels
   window.after(1,compute)



compute()
window.mainloop()


What I would like to do is (pseudocode):

#HOW TO DO THE FOLLOWING PART?
while running:
  compute()
  if iteration % 3 == 0: #we want to draw only every 3 computed configurations
    redraw_canvas() 

An example of my code is:


import tkinter as tk
import numpy as np

window = tk.Tk()
window.geometry("600x600")
canv_w= 480
square_w = 8 #size of one element of the matrix
N = 60     # size of matrix
canvas=tk.Canvas(window,width=480,height=480)
canvas.pack()
my_image=tk.PhotoImage(width=480,height=480)
canvas.create_image((3, 3),image=my_image,anchor="nw",state="normal")


def pixel(matrix, i,j):

        if matrix[i,j]==-1:
            temp="#cc0000"
        elif matrix[i,j]==1:
            temp="#7CFC00"
        my_image.put(temp,to=(i*square_w,j*square_w,(i 1)*square_w,(j 1)*square_w))


def compute():
   global iteration

   div, rem = divmod(iteration, N)
   #print("I'm about to change pixel with column div and row rem)
   print(div % N, rem)
   matrix[div % N, rem]*=-1 # compute changes to the matrix (in this case we invert the colour of one pixel at each iteration)

   for i in range(N):
        for j in range(N):
            pixel(matrix,i,j) # transfer the corresponding changes to the photoimage

   iteration =1
   window.after(1,compute)


iteration=0
running=1
matrix=np.random.choice([-1, 1], (N,N), p=[0.4,0.6])

compute()
window.mainloop()

CodePudding user response:

Just call window.update() after you calculated each pixel value.

import tkinter as tk
import numpy as np

window = tk.Tk()
window.geometry("600x600")
canv_w= 480
square_w = 8 #size of one element of the matrix
N = 60     # size of matrix
canvas=tk.Canvas(window,width=480,height=480)
canvas.pack()
my_image=tk.PhotoImage(width=480,height=480)
canvas.create_image((3, 3),image=my_image,anchor="nw",state="normal")


def pixel(matrix, i,j):
    if matrix[i,j]==-1:
        temp="#cc0000"
    elif matrix[i,j]==1:
        temp="#7CFC00"
    my_image.put(temp,to=(i*square_w,j*square_w,(i 1)*square_w,(j 1)*square_w))

def compute():
   global iteration
   div, rem = divmod(iteration, N)
   #print("I'm about to change pixel with column div and row rem)
   print(div % N, rem)
   matrix[div % N, rem]*=-1 # compute changes to the matrix (in this case we invert the colour of one pixel at each iteration)
   for i in range(N):
        for j in range(N):
            pixel(matrix,i,j) 
        if not (i   1) % 3:
            window.update()  # <-- added this
   window.after(1,compute)


iteration=0
running=1
matrix=np.random.choice([-1, 1], (N,N), p=[0.4,0.6])

compute()
window.mainloop()
  • Related