'Dynamically updating polygon shape in tkinter window

I'm writing a program for my raspberry pi4 for my Master's project which sounded so simple at first but for some reason Python is causing me grief.

In short - I have created a tkinter canvas with a polygon centred on the canvas. The shape of this polygon will depend upon the value of a counter.

The count is controlled by a blink event from a neurosky mindwave headset - this count is working (mostly).

What I want to then do is update the canvas to put the new points for the polygon into the pack but nothing I have tried seems to work. The closest I got was trying a .redraw() command which drew an infinite number of windows before I pulled the plug.

I am not a complete novice to coding having taught many languages in my time but have never used python before and am clearly missing a very simple step which will cause everything to fall out.

I will try to modify the code to use a keyboard press rather than a headset and add it below later if folk think it will help.

import keyboard
import time
from tkinter import *
count = 0
points = [250,250,350,250,350,350,250,350]
root = Tk()
while True:

# set window to middle of screen
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()
    xcoord = screen_width/2-300
    ycoord = screen_height/2 - 300
    root.geometry("%dx%d+%d+%d" % (600,600,xcoord,ycoord))
#set up canvas size and background colour
    canvas1 = Canvas(root, relief = FLAT,width = 600, height = 600, background = "blue")
#set up buttons shape and colour
    button = canvas1.create_polygon(points, fill="darkgreen", outline="yellow")
    canvas1.pack()
    if keyboard.is_pressed("f"):
        if count < 4:
            count += 1
        elif count == 4:
            count = 0
    time.sleep(0.1)

    if count == 0:
        points = [250,250,350,250,350,350,250,350]
    elif count == 1:
        points = [300,100,500,500,100,500]
    elif count == 2:
        points = [200,100,400,100,300,500]
    elif count == 3:
        points = [100,300,500,100,500,500]
    elif count == 4:
        points = [100,100,100,500,500,300]
    print(count)
    root.update()


Solution 1:[1]

You need to delete the old polygon and create new one. Also don't use while loop in tkinter application. For your case, you can bind a callback on <Key> event and update the polygon in the callback:

import tkinter as tk

count = 0
points = [
    [250,250,350,250,350,350,250,350],
    [300,100,500,500,100,500],
    [200,100,400,100,300,500],
    [100,300,500,100,500,500],
    [100,100,100,500,500,300],
]

root = tk.Tk()

# set window to middle of screen
screen_width = root.winfo_screenwidth()
screen_height = root.winfo_screenheight()
xcoord = screen_width//2 - 300
ycoord = screen_height//2 - 300
root.geometry("%dx%d+%d+%d" % (600,600,xcoord,ycoord))

#set up canvas
canvas1 = tk.Canvas(root, relief=tk.FLAT, background="blue")
canvas1.pack(fill=tk.BOTH, expand=1)

# create the polygon with tag "button"
canvas1.create_polygon(points[count], fill="darkgreen", outline="yellow", tag="button")

def on_key(event):
    global count
    if event.char == 'f':
        count = (count + 1) % len(points)
        print(count)
        canvas1.delete("button") # delete the old polygon
        canvas1.create_polygon(points[count], fill="darkgreen", outline="yellow", tag="button")

root.bind("<Key>", on_key)

root.mainloop()

Solution 2:[2]

You can update any parameters of a shape.

canvas.itemconfigure(shape1_id_or_tag, fill="green")
canvas.itemconfigure(shape2_id_or_tag, fill="#900", outline="red", width=3)

But for your situation try '.coords()':

canvas1.coords("Button", points[count])

Source: https://anzeljg.github.io/rin2/book2/2405/docs/tkinter/canvas-methods.html

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 acw1668
Solution 2 LeJandr