15

I'm trying to simulate an American traffic light, with 3 circles on a rectangle, all drawn on a set Canvas. The simulation is supposed to mirror "animation" by changing which light is displayed every 2 seconds in the following order: green > yellow > red > green, etc forever.

The only way I can think of to do this is by using a canvas.move(), canvas.after(), canvas.update() pattern to move a filled oval object to superimpose one unfilled circle at a time. I've gotten the logic down to move a circle at the proper speed and in the correct order. The thing is, I just instantiate a circle filled with "green", but I can't change it to be "yellow" or "red" using this method. It seems silly to have to canvas.delete("filled") and redraw it in a new place with a different fill every 2 seconds, because that's a lot to do for such a simple program.

Question 1: Is there a way I can just alter the fill option for my filled Canvas object at will, using some method or other means?

Question 2: Am I approaching this scenario incorrectly? Is there a better way to simulate this?

martineau
  • 119,623
  • 25
  • 170
  • 301
Brad Rice
  • 1,334
  • 2
  • 17
  • 36

1 Answers1

31

Yes you should be able to change settings of the canvas with config().

Likewise, use itemconfig() to change items on the canvas. This does require that you save a handle to the item or tag them.

Example based on tkinterbook:

item = canvas.create_line(xy, fill="red")

canvas.coords(item, new_xy) # change coordinates
canvas.itemconfig(item, fill="blue") # change color
Junuxx
  • 14,011
  • 5
  • 41
  • 71
  • 1
    Thank you! How exactly do I call that? Like, what object do I call it on? All I've got is a canvas `self.canvas`, and a tag on the object `"filled"`. Is that enough info? I tried `self.canvas["filled"]` but that didn't seem to work. I'm more of a Ruby guy, so accessing attributes in Python is new to me. – Brad Rice Oct 20 '12 at 19:15
  • @Brad: This answer is less than perfectly clear IMO. The widget `w` in this case is the `tkinter.Canvas`, so you would do it via `self.canvas.itemconfig(i, fill='blue')` where `i` is the canvas item's id or tag. – martineau May 26 '21 at 01:30
  • Wow, so sad that effbot is gone. Thanks for the explanation and maintenance, @martineau. Since the original example is gone now, I might as well change the variables names to something easier to read. – Junuxx May 26 '21 at 07:39
  • Junuxx: Yeah, Fredrik the effbot Lundh's great unfinished-but-often-cited [**tkinterbook**](https://web.archive.org/web/20200201021036/http://effbot.org/tkinterbook/) has finally been put out of its misery — too bad the author never got around to completing it since it was closest thing that's ever existed to actual documentation for the `tkinter` module (one of many) he created. – martineau May 26 '21 at 10:19
  • ...Nevertheless, the excerpt of code from it you originally had in your answer was taken out-of-context rendering it nearly incomprehensible wrt the OP's question. Despite that you've left it that way nearly nine years before ever bothering to improving it…but I guess at least you finally have. – martineau May 26 '21 at 10:19
  • 1
    That last part comes across rather hostile. Cheers. – Junuxx May 26 '21 at 16:21