0

I have created a bunch of OVALS. And have defined a variable (w_oval) to be used in a FOR. Itemconfigure does not accept this variable. Something about immutable variables? How do I define a variable for the itemconfigure? I know I'm missing some philosophy here.

b1_oval = bottom_frame.create_oval( 25,180,65,205, fill='')
b2_oval = bottom_frame.create_oval( 25,180,65,205, fill='')
#... more bn_oval

i_oval = 0
w_oval = ''
ovalLONG = [-90,-75,-60,-45,-30,-15,0,15,30,45,60,75,90]
for j in ovalLONG:
    i_oval = i_oval + 1
    w_oval = str('b'+str(i_oval)+'_oval') # Not flying Wilbur
    if i == j:
           bottom_frame.itemconfigure(w_oval, fill='goldenrod3')
Tango
  • 1
  • 1
    This is simply not how variables work. Store your ovals in a list or dictionary. – Bryan Oakley May 30 '18 at 23:49
  • Thank you Bryan. But why does itemconfigure not accept a formated string? Works: b2_oval = bottom_frame.create_oval( 75,180,115,205, fill='') bottom_frame.itemconfigure(b2_oval, fill='goldenrod3') Why does this formatted string not? w_oval = 'b'+str(i_oval)+'_oval' bottom_frame.itemconfigure(w_oval, fill='goldenrod3') – Tango May 31 '18 at 10:53
  • itemformat _does_ accept a formatted string. The `itemconfigure` is working, but the string you're computing isn't associated with anything in the canvas. It looks the same as the variable name, but it's just a string. The canvas has no idea that you've stored the id of an object in a variable with a name that matches the string. – Bryan Oakley May 31 '18 at 12:01

1 Answers1

0

Consider this line of code:

b1_oval = bottom_frame.create_oval( 25,180,65,205, fill='')

In the above code, create_oval is returning an integer identifier which represents the object that was created. You are storing this in a variable named b1_oval.

Now consider this code:

for j in ovalLONG:
    i_oval = i_oval + 1
    w_oval = str('b'+str(i_oval)+'_oval') # Not flying Wilbur
    if i == j:
           bottom_frame.itemconfigure(w_oval, fill='goldenrod3')

First, you are creating a string that looks like "b1_oval". You are storing this string in a variable named w_oval. In other words, it's no different than if you did w_oval = "b1_oval".

When you call itemconfigure(w_oval, ...) it is identical to calling `itemconfigure("b1_oval", ...).

That first parameter is taken by the canvas to be a tag or an id. Since it's not an integer it is treated as a tag. You have not created any objects on the canvas with the tag `"b1_oval", so nothing has changed. Just to be clear: tags and variable names are two completely different things.

You have one of two options: either give each oval a tag that matches that pattern (via the tag option), or store the ids in a way that you can use in the loop.

The second of those solutions is the best and easiest in my opinion. Instead of creating a bunch of variables that have numbers in the name, store the ids in a list or dictionary. Then it's just a simple lookup, without having to compute the name of a variable.

For example:

ovals = []
ovals.append(bottom_frame.create_oval(...))
ovals.append(bottom_frame.create_oval(...))
...
for j in ovalLONG:
    if i == j:
        bottom_frame.itemconfigure(ovals[i], ...)

I doubt the above is exactly what you want, because I don't know where you're computing i -- it's not in the code you provided. Still, the point is that you save the object ids in a list rather than trying to compute a variable name.

The main disadvantage to using lists is that you can't control the indexes. Lists always start counting at zero, so the first oval you create will always be ovals[0] even if you want to start the counting at 1.

Another option is to use a dictionary rather than a list, which lets you use any arbitrary names or numbers for the ovals, and doesn't require that they are linear.

ovals = {}
ovals[1] = bottom_frame.create_oval(...)
ovals[100] = bottom_frame.create_oval(...)
...
i = 100
...
bottom_frame.itemconfigure(ovals[i], ...)
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685