0

I have this code:

from tkinter import *
import os
import glob
from PIL import Image, ImageTk

root = Tk()

tkvar = StringVar()

# Directory
directory = "C:/Users/label/Desktop/test folder/"
choices = glob.glob(os.path.join(directory, "*jpg")) # all choices ending with .jpg in the directory above

# Images, placing the image onto canvas
def change_dropdown():
    imgpath = tkvar.get()
    img = Image.open(imgpath)
    photo = ImageTk.PhotoImage(img)
    label2.image = photo
    label2.configure(image=photo)

#widgets
msg1 = Label(root, text = "Choose here")
msg1.grid(column = 0, row = 0)
popupMenu = OptionMenu(root, tkvar, *choices) #Dropdown menu of all sign off Sheets that need signing
popupMenu.grid(row=1, column=0)
display_label = label2 = Label(root, image=None)
display_label.grid(row=2, column=0, rowspan = 200)
open_button = Button(root, text="Open", command=change_dropdown) # opens the directory and opens selected image
open_button.grid(row=20, column=0)

root.mainloop()

What it does:

It's a simple app that allows me to click a directory and open the image.

My issue:

If I remove one of the .jpg files from the folder, how can I update the optionMenu values to match the current folder? Because If I remove a file when running the script, option menu does not update automatically

Here is a code I have tried from Updating OptionMenu from List but this does not update anything..

from tkinter import *
import os
import glob
from PIL import Image, ImageTk

root = Tk()

tkvar = StringVar()

# Directory
directory = "C:/Users/label/Desktop/test folder/"
choices = glob.glob(os.path.join(directory, "*jpg")) # all choices ending with - to sign.jpg in the directory above
tkvar.set('...To Sign Off...') # set the default option

# Images, placing the image onto canvas
def change_dropdown():
    imgpath = tkvar.get()
    img = Image.open(imgpath)
    photo = ImageTk.PhotoImage(img)
    label2.image = photo
    label2.configure(image=photo)

#widgets
msg1 = Label(root, text = "Choose here")
msg1.grid(column = 0, row = 0)
popupMenu = OptionMenu(root, tkvar, *choices) #Dropdown menu of all sign off Sheets that need signing
popupMenu.grid(row=1, column=0)
display_label = label2 = Label(root, image=None)
display_label.grid(row=2, column=0, rowspan = 500)
open_button = Button(root, text="Open", command=change_dropdown) # opens the directory and opens selected image
open_button.grid(row=502, column=0)

def update_option_menu():
    menu = popupMenu["menu"]
    menu.delete(0, "end")
    for string in choices:
        menu.add_command(label=string,
                         command=lambda value=string: tkvar.set(value))

update_button = Button(root, text='Update option menu', command=update_option_menu)
update_button.grid(column=0, row=2)




root.mainloop()
Valuez
  • 15
  • 4
  • Possible duplicate of [Updating OptionMenu from List](https://stackoverflow.com/questions/28412496/updating-optionmenu-from-list) – stovfl Oct 28 '19 at 20:42
  • ***"does not update anything"***: You are using the same `choices` – stovfl Oct 28 '19 at 21:18

1 Answers1

0

Maybe by just calling an after() function to refresh the list. So something like:

EDIT: Removed the optional command to tk._setit() because that actually causes the change_dropdown() to fail as it doesn't have any parameters, and realized to constantly refresh you want to call this recursively.

def refresh_list():
    new_list = glob.glob(os.path.join(directory, "*jpg"))

    # update the option menu
    popupMenu['menu'].delete(0, 'end')
    for item in new_list:
        popupMenu['menu'].add_command(label=item, command=tk._setit(tkvar, item)
    # Keep refreshing
    root.after(10, refresh_list)

...
# Initial call to refresh
root.after(10, refresh_list)

I haven't test it, but the idea is to use the refresh_list() function to check the directory files, delete the current item options, and add the new item options with the same command to set your tk.StringVar(), the label on the dropdown, and the command that gets executed on click to remain the same (change_dropdown).

  • Start an interpreter, import tkinter, and type help(tk._setit). But, there's a `command` optional parameter on the `OptionMenu` that has a callback which has an added parameter `value` that is the option the User selected from the dropdown. So, the `tk._setit` is "Internal class. It wraps the command in the widget OptionMenu.". Also, by looking at this, you're button is what calls change_dropdown, so you might want to remove the `change_dropdown` from the `tk._setit`. – Thomas Higginson Oct 28 '19 at 21:10
  • I have added a button, set command to `refresh_list` now it works! – Valuez Oct 28 '19 at 21:17
  • I updated the answer, you should realize that I introduced a bug accidentally :/ but it should work now :) – Thomas Higginson Oct 28 '19 at 21:21