Home > Back-end >  How to get the values of all the OptionMenu widgets within a frame inside a canvas in Tkinter
How to get the values of all the OptionMenu widgets within a frame inside a canvas in Tkinter

Time:03-30

I'm writing a minimalist image tagging app that will list out all the image files in a specific location alongside a dropdown menu to select the options for tagging the image. Once the images are tagged, I need to save the changes to a JSON file and I've got a button for that. How can we read all the options selected so that it can be written into a file?

Following is the code so far:

from tkinter import N, RIGHT, Button, OptionMenu, Scrollbar, StringVar, Tk, Canvas, Frame, Label

class App:
    def __init__(self):
        self.root = Tk()
        self.tags = ['Apples', 'Oranges', 'Berries']
        self.GetRows()    
        self.SaveButton()
        self.root.mainloop()

    def GetRows(self):

        self.canvas = Canvas(self.root)
        self.scroll_y = Scrollbar(self.root, orient="vertical", command=self.canvas.yview)
        self.frame = Frame(self.canvas)
        
        lst = [f"A01{str(i)}.JPG" for i in range(100)]

        for idx, r in enumerate(lst):
            filename = Label(self.frame, text=r)
            filename.grid(row=idx 2, column=0, sticky=N)
            
            label = StringVar()
            drop = OptionMenu(self.frame, label, *self.tags)
            drop.grid(row=idx 2, column=1)
        
        # put the frame in the canvas
        self.canvas.create_window(0, 0, anchor='nw', window=self.frame)

        # make sure everything is displayed before configuring the scrollregion
        self.canvas.update_idletasks()

        self.canvas.configure(scrollregion=self.canvas.bbox('all'),
                 yscrollcommand=self.scroll_y.set)
        
        self.canvas.pack(fill='both', expand=True, side='left')
        self.scroll_y.pack(fill='y', side='right')


    def SaveState(self):
        pass

    def SaveButton(self):
        self.save_button = Button(self.root, text="Save Changes", padx=50, pady=10, command=self.SaveState)
        self.save_button.pack(side=RIGHT)
        


if __name__ == '__main__':
    App()

The SaveState method is what will be used to write the selections so far into a file.

Thanks in advance!

CodePudding user response:

In order to make OptionMenu results available try modifying your code so that all StringVars are accessible outside of GetRows.

    def GetRows(self):
        ...
        # Define label as a list
        self.label = []
        for idx, r in enumerate(lst):
            filename = Label(self.frame, text=r)
            filename.grid(row=idx 2, column=0, sticky=N)
            
            label = StringVar()
            drop = OptionMenu(self.frame, label, *self.tags)
            drop.grid(row=idx 2, column=1)
            # Save StringVar reference
            self.label.append(label)
        ...

    def SaveState(self):
        self.data = dict()
        # Retrieve results into dictionary
        for i, a in enumerate(self.label):
            self.data[f"A_{i}"] = a.get()
        print(self.data)

Then use json.dump(self.data, a_file) to save it

  • Related