Hello I have a tuple in python with colours that are related to squares that are drawn in the canvas by the following dictionary:
colour_mapping = {0: "red", 1: "green", 2: "blue" , 3:"purple"}
To be more specific for example a node at the tuple is:
((2, 3), (3, 3))
This means that 4 squares should be drawn this way:
blue square purple square
purple square purple square
and then their colours should be changed accordingly to the next node in my tuple
To do this I iterate the tuple and for each element I draw a new rectangle at the canvas and then I call the time.sleep()
function in order to give time to the user to see the differences to the previous state.
My problem is that only the last node is rendered correctly while all the others aren't shown. Can you help me?
Here is my code so far:
self.parent.title("AlienTiles")
self.style = Style()
self.style.theme_use("default")
self.frame = Frame(self, relief=RAISED, borderwidth=1)
self.frame.pack(fill=BOTH, expand=1)
self.canvas = Canvas(self.frame)
self.canvas.pack(fill=BOTH, expand=1)
self.pack(fill=BOTH, expand=1)
for i in range(len(path)) : #the tuple is path
state = path[i].state
print state
time.sleep(1)
y_offset=10
for x in state:
start_x=40
start_y=10
i=1
x_offset=0
for y in x:
x0=(start_x*i)+x_offset
y0=(start_y*i)+y_offset
x1=x0+size
y1=y0+size
colour=colour_mapping[y]
print colour
self.canvas.create_rectangle(x0, y0, x1, y1, fill=colour)
x_offset=x_offset+size+10
y_offset=y_offset+size+10
All in all, I try to make an animation described above. Is there anything I don't think correctly or something to refresh the canvas at each loop?
Go to app/extension store (Chrome Web Store, Firefox Add-Ons, Microsoft Edge Add-ons Store, etc.). Enter “auto-refresh” in the search bar. Choose an extension. Follow the prompts to download and install the extension onto your browser toolbar.
The only way for the canvas to refresh is for the event loop to service "redraw" events. In your loop you're never giving the event loop a chance to update, so you don't see any changes. The quick fix is to call self.
To change a particular image, we can configure the canvas by using the itemconfig() constructor. It takes image files which need to be updated and displayed them on the window. Use three images of your choice and save them in the same project directory.
Update method processes all the pending idle tasks, unvisited events, calling functions, and callbacks. The method is applicable for updating and processing all the events or tasks such as redrawing widgets, geometry management, configuring the widget property, etc.
The only way for the canvas to refresh is for the event loop to service "redraw" events. In your loop you're never giving the event loop a chance to update, so you don't see any changes.
The quick fix is to call self.canvas.update_idletasks
, but that's just a hack and not a proper solution.
The proper way to do animation is to use the event loop to do the iterations. You do this by placing work to be done on a queue -- in this case, the idle event queue. You can place things on this queue with the after
command.
What you should do is write a function that does one iteration of your animation. Essentially, take everything in your while loop and move it to a function. Then, arrange for that function to be continually be called as long as there is work to do. You can either place the call to after
in that function, or have a separate function controlling the animation.
Roughly speaking, the solution looks like this:
def do_one_frame(self, ...):
# do whatever you need to draw one frame
if (there_is_more_work_to_be_done):
self.after(10, do_one_frame)
This will draw one frame of your animation, check to see if there are any new frames to be drawn, and then arranges for the next frame to be drawn in 10ms. Of course, you can set that value to whatever you want in order to control the speed of the animation.
There are working examples of this technique on this website. For example, see https://stackoverflow.com/a/25431690/7432
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With