Determining row number of chosen OptionMenu but possibility to create within same variable - Tkinter

StackOverflow https://stackoverflow.com/questions/11414702

Pregunta

I have the following code where I ask the user to open a text which can include several rows within a section of data.

I then require for each row an OptionMenu to be created. My problem is that I need to do different things for each option menu and apply it only to that specific row in the 'grid'. I cannot do this as I'm creating them all under the same name and don't understand how to do differently.

with askopenfile(filetypes=[(".txt files","*.txt")], title='Import', mode='r') as f: 
    data_dict=parse_file(f) 


info=data_dict['three'] 
i = 2
for row in info:
    # Create row in 'table' for each output
    no_1, code, value = row             # Obtain results
    def three( code ):
        c = { "1" : "1",
              "2" : "2",
              "3" : "3" }
        try:
            return c[code]
        except KeyError:
            return "None"


    variablelist = StringVar(self.frame_table)
    variablelist.set("Fixed")
    self.list1 = OptionMenu(self.frame_table, variablelist, "Fixed", "List", "Min", "Max", command=self.ChoiceBox)
    self.list1.grid(row=i, column=6, sticky="nsew", padx=1, pady=1)
    i = i + 1

For example, I would like to create an extra box next to the second row out of three but as the third row is created last, when I try to obtain the grid info, I can only add it onto the third row.

My reasoning for having done it like this is because I don't always know the amount of rows and I didn't want to create lots of lines of code creating an option menu separately each time (even if I did know the number of rows).

¿Fue útil?

Solución

Your question is very unclear, mostly because your example doesn't make any sense. Why, for example, are you redefining the function three on every iteration, yet you never use it?

Regardless, maybe the following example will help you. It creates three option menus, associates a variable with each, and has each of them call the same procedure when the value changes. By default this method will be given the new value of the option menu; by using a lambda function we can also pass the row number to the function.

import Tkinter as tk

# data for the example
info = (
    ("1.1","1.2","1.3"),
    ("2.1","2.2","2,3"),
    ("3.1","3.2","3.3"),
)

class SampleApp(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.status = tk.Label(self, anchor="w")
        self.frame_table = tk.Frame(self, background="black")
        self.frame_table.grid_columnconfigure(1, weight=1)
        self.frame_table.grid_columnconfigure(2, weight=1)
        self.frame_table.grid_columnconfigure(3, weight=1)

        self.status.pack(side="bottom", fill="x")
        self.frame_table.pack(side="top", fill="x", padx=10, pady=10)

        for row_number, row_data in enumerate(info):
            no_1, code, value = row_data
            label = tk.Label(self.frame_table, text="row %d" % row_number, background="gray")
            col1  = tk.Label(self.frame_table, text=no_1)
            col2  = tk.Label(self.frame_table, text=code)
            col3  = tk.Label(self.frame_table, text=value)

            # N.B. 'value' is automatically passed to
            # the command by tkinter; we're adding
            # an extra parameter, 'row' 
            command=lambda value, row=row_number: self.ChoiceBox(value, row)
            stringvar = tk.StringVar(self.frame_table)
            stringvar.set("Fixed")
            option_menu = tk.OptionMenu(self.frame_table, stringvar, 
                                        "Fixed","List","Min","Max", 
                                        command=command)
            label.grid(row=row_number, column=0, sticky="nsew", padx=1, pady=1)
            col1.grid(row=row_number, column=1, sticky="nsew", padx=1, pady=1)
            col2.grid(row=row_number, column=2, sticky="nsew", padx=1, pady=1)
            col3.grid(row=row_number, column=3, sticky="nsew", padx=1, pady=1)
            option_menu.grid(row=row_number, column=6, sticky="nsew", 
                             padx=1, pady=1)

    def ChoiceBox(self, value, row_number):
        self.status.config(text="you set row %d to '%s'" % (row_number, value))

app = SampleApp()
app.mainloop()

Otros consejos

self.variablelists=[]
self.lists=[]
for row in info:
    # Create row in 'table' for each output
    no_1, code, value = row             # Obtain results
    def three( code ):    #don't know what this is for, but if it's necessary later, this is more clean than your previous code.
        return c if c in "123" else "None"    

    variablelist = StringVar()
    variablelist.set("Fixed")
    self.variablelists.append(variablelist)
    list1 = OptionMenu(self.frame_table, variablelist, "Fixed", "List", "Min", "Max", command=self.ChoiceBox)
    list1.grid(row=i, column=6, sticky="nsew", padx=1, pady=1)
    self.lists.append(list1)
    i += 1

Now you have a handle on each of your option menus.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top