-3

I have a window that contains up to twelve lines of data from a matrix. Because I use a loop, I have to use a "variable label." One of these variable labels There are eight of them) uses an Option Menu to allow the user to pick from a list, the example here is "0", "1", "2", "3".

I use the i=my_num before the colon because out of the twelve lines, the user might be changing line three.

The problem is, no matter what I do, the "print(f'{i}, {gn.get()}, {final_roster}')" statement will "overwrite" the "i" value with the "gn" value.

Changing this variable for the first line to a value of "3" should look like this: 1, 3, {1: 'B@Griffin@GRF-3M@1521@1@1521@A@A@N@5@4'}

But actually returns this: 3, 3, {1: 'B@Griffin@GRF-3M@1521@1@1521@A@A@N@5@4'}

from tkinter import *
from tkinter import Label
from tkinter import messagebox
from tkinter import LEFT
from tkinter.ttk import Label, Entry
from tkinter.filedialog import askopenfilename
from tkinter import Tk, Canvas, Frame, BOTH
import win32api


root = Tk()

def NewList(root):
    rndwin = Toplevel(root)
    rndwin.geometry("775x360+10+10")
    rndwin.title("Define Selection Parameters")
    pick3 = [
        "0",
        "1",
        "2",
        "3"
    ]
    # This line is actually in a loop and draws up to twelve of them.
    globals()['roster_gun%s' % my_num] = OptionMenu(rndwin, gunnry, *pick3, command=lambda i=my_num: gunneryv(root, rndwin, i, gunnry, final_roster, bv_array, roster_sz, base_files))
    globals()['roster_gun%s' % my_num].place(x=10, y=10)

def gunneryv(root, rndwin, i, gn, final_roster, bv_array, roster_sz, base_files):
    print(f'{i}, {gn.get()}, {final_roster}')
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
  • I don't see any `for`-loop – furas Jan 15 '20 at 00:01
  • Python has dictionary to keep variables like `data['roster_gun%s' % my_num] = ...` and later you get it the same way `print( data['roster_gun%s' % my_num] )` - you don't have to use `globals()` – furas Jan 15 '20 at 00:02
  • create minimal working code so we could run it and see problem. I don't see any `loop` in code and I can't run it so I don't see where is problem. – furas Jan 15 '20 at 00:05
  • you create only one `OptionMenu` so you have only one value in `i=my_num` - you can't have three different values - you missunderstood something. – furas Jan 15 '20 at 00:08
  • @furas, I do, because I have to constantly destroy these labels after going to other routines. – Memphismark Jan 15 '20 at 00:11
  • I would have to include over 200+ lines of code to get this working. – Memphismark Jan 15 '20 at 00:12
  • `OptionMenu` runs `command` with index of value which you selected and you have to get in `lambda` and you don't have to assign `my_num` to variable - use it dirrectly. – furas Jan 15 '20 at 00:14

1 Answers1

0

OptionMenu executes command with one argument - index of selected item - and it assign it to your i in your code.

You don't run code in for-loop so you don't need use i=my_num - you can put it directly

command=lambda selected: gunneryv(root, rndwin, my_num, gunnry, final_roster, bv_array, roster_sz, base_files)

But if you will run in for-loop then you may have to use i=my_num but as second argument

command=lambda selected, i=my_num: gunneryv(root, rndwin, i, gunnry, final_roster, bv_array, roster_sz, base_files)

BTW: Python has dictionary to keep variables like this

roster_gun = dict()

roster_gun[my_num] = tk.OptionMenu(...)
roster_gun[my_num].place(x=10, y=10)

and you don't have to use globals() for this

furas
  • 134,197
  • 12
  • 106
  • 148
  • Thank you. :-) I am running it in a loop, the labels go from roster_gun1 to roster_gun12. I have also gotten other elements of this routine to work not using OptionMenu, so I know it's good code. The problem is when using OptionMenu, the "i" value is ALWAYS the value of the "gunnry" value. This is what is killing me. – Memphismark Jan 15 '20 at 00:41
  • If you have a solution for the globals(), I'm all ears. Because of how the window is built, I have to constantly delete and redraw elements, always after I have invoked other routines. Once I am out of the routine they were created in, when I come back to that first routine, the ".destroy()" function no longer works, unless it is a global. – Memphismark Jan 15 '20 at 00:44
  • you have to define dictionary outside all functions/methods and then it is global dictionary and you can use it inside functions/methods even without using word `global`. Eventually you can send this dictionary as argument to function which will have to add element to dictionary. – furas Jan 15 '20 at 01:09