Use loop to create x number of tkinter OptionMenu - python

I am attempting to create an arbitrary number of optionmenus, but have trouble when trying to pull the StringVar() selected by each optionmenu.
Goal: Create an arbitrary number of optionmenus with consecutive names (up to that arbitrary number) and consecutive variable names keeping track of the current optiomenu value
For example if an optionmenu is as follows:
import tkinter as tk
from tkinter import *
root = tk.Tk()
root.geometry()
dropdown1 = StringVar()
Dropdownoptions = [
"option1",
"option2",
"option3"
]
dropdownfirst = tk.OptionMenu(root, dropdown1, *Dropdownoptions)
dropdownfirst.grid(column=0, row=0)
root.mainloop()
If using a dictionary I do not know how to pull the values out of each Optionmenu. When looking at other questions about the use of dictionaries to create variables, most answers boil down to "Learn How to Use Dictionaries" instead of answering the questions.
There was a very similar problem posted in Tkinter Create OptionMenus With Loop but sadly it is not applicable in my case.
New code with grid and non-working button:
import tkinter as tk
def erase_option():
for (name, var) in options.items():
print(var.get())
# print(options['optionmenu4'])
# This just places label over dropdown, doesnt successfully take place for removal
labelforemoval = tk.Label(text=" ")
labelforemoval.grid(column=0, row=4)
labelforemoval.grid_forget()
root = tk.Tk()
Dropdownoptions = [
"option1",
"option2",
"option3"
]
maxval = 10
options = {}
for om, x in zip(range(maxval), range(maxval)):
name = f"optionmenu{om}"
var = tk.StringVar()
options[name] = var
name = tk.OptionMenu(root, var, *Dropdownoptions)
name.grid(column=0, row=x)
button = tk.Button(root, text="Erase 5th option", command=erase_option)
button.grid(column=0, row=maxval)
root.mainloop()

Give each optionmenu its own StringVar instance. Save those instances in a list or dictionary. To get the values, iterate over the list.
The following code creates a dictionary named options. It creates a series of variables and optionmenus in a loop, adding each variable to this options dictionary. The function print_options iterates over the list printing out the key and value for each option.
import tkinter as tk
def print_options():
for (name, var) in options.items():
print(f"{name}: {var.get()}")
root = tk.Tk()
Dropdownoptions = [
"option1",
"option2",
"option3"
]
options = {}
for om in range(10):
name = f"Option {om}"
var = tk.StringVar(value="")
options[name] = var
om = tk.OptionMenu(root, var, *Dropdownoptions)
om.pack()
button = tk.Button(root, text="Print Options", command=print_options)
button.pack(side="bottom")
root.mainloop()

Related

is there a way to create dropdown menu like this? [duplicate]

I am creating a GUI that builds information about a person. I want the user to select their birth month using a drop down bar, with the months configured earlier as a list format.
from tkinter import *
birth_month = [
'Jan',
'Feb',
'March',
'April'
] #etc
def click():
entered_text = entry.get()
Data = Tk()
Data.title('Data') #Title
label = Label(Data, text='Birth month select:')
label.grid(row=2, column=0, sticky=W) #Select title
How can I create a drop down list to display the months?
To create a "drop down menu" you can use OptionMenu in tkinter
Example of a basic OptionMenu:
from Tkinter import *
master = Tk()
variable = StringVar(master)
variable.set("one") # default value
w = OptionMenu(master, variable, "one", "two", "three")
w.pack()
mainloop()
More information (including the script above) can be found here.
Creating an OptionMenu of the months from a list would be as simple as:
from tkinter import *
OPTIONS = [
"Jan",
"Feb",
"Mar"
] #etc
master = Tk()
variable = StringVar(master)
variable.set(OPTIONS[0]) # default value
w = OptionMenu(master, variable, *OPTIONS)
w.pack()
mainloop()
In order to retrieve the value the user has selected you can simply use a .get() on the variable that we assigned to the widget, in the below case this is variable:
from tkinter import *
OPTIONS = [
"Jan",
"Feb",
"Mar"
] #etc
master = Tk()
variable = StringVar(master)
variable.set(OPTIONS[0]) # default value
w = OptionMenu(master, variable, *OPTIONS)
w.pack()
def ok():
print ("value is:" + variable.get())
button = Button(master, text="OK", command=ok)
button.pack()
mainloop()
I would highly recommend reading through this site for further basic tkinter information as the above examples are modified from that site.
Here Is my function which will let you create a Combo Box with values of files stored in a Directory and Prints the Selected Option value in a Button Click.
from tkinter import*
import os, fnmatch
def submitForm():
strFile = optVariable.get()
# Print the selected value from Option (Combo Box)
if (strFile !=''):
print('Selected Value is : ' + strFile)
root = Tk()
root.geometry('500x500')
root.title("Demo Form ")
label_2 = Label(root, text="Choose Files ",width=20,font=("bold", 10))
label_2.place(x=68,y=250)
flist = fnmatch.filter(os.listdir('.'), '*.mp4')
optVariable = StringVar(root)
optVariable.set(" Select ") # default value
optFiles = OptionMenu(root, optVariable,*flist)
optFiles.pack()
optFiles.place(x=240,y=250)
Button(root, text='Submit', command=submitForm, width=20,bg='brown',fg='white').place(x=180,y=380)
root.mainloop()

python tk different functions depending on drop down list item selected

I am trying to call a different function in a drop down list depending on what the user has selected. For example, say i want to have 2 functions that are called depending on if function1 or function2 is chosen in a drop down list.
this is the call for tk i used:
from TK import *
This is how i write option menus:
Dropdown = OptionMenu("function1","function2",command = run_a_function)
this runs the same function no matter which option is chosen.
is there a way to assign a function to different options in the option menu?
Edit: Added two functions.
Is this what you wanted?
import tkinter as tk
root = tk.Tk()
a = tk.StringVar()
a.set("default")
var = tk.StringVar(root)
var.set("Select")
def _this_what_you_wanted():
print(f'Is this what you wanted?')
def _this_is_second_function():
print(f'this is second function')
def run_a_function(x):
if x == "function1":
_this_what_you_wanted()
else:
a.set("function2")
_this_is_second_function()
opt = tk.OptionMenu(root, var, "function1","function2", command = run_a_function)
opt.pack()
root.mainloop()
is there a way to assign a function to different options in the option menu?
Strictly speaking, no. You can only define a single function to an OptionMenu. However, that single function can use a map to determine which function can run.
Here's an example that creates a dictionary with functions and the names that should appear in the optionmenu. When the function tied to the optionmenu runs, it gets the value of the optionmenu, uses that to lookup the function in the dictionary, then runs that function.
import tkinter as tk
def func1():
label.configure(text="func1 called")
def func2():
label.configure(text="func2 called")
functions = {
"function 1": func1,
"function 2": func2,
}
def run_a_function(*args):
func_name = function_var.get()
func = functions.get(func_name, None)
func()
root = tk.Tk()
root.geometry("400x200")
function_var = tk.StringVar(value="Choose a function")
dropdown = tk.OptionMenu(root, function_var, *functions.keys(), command=run_a_function)
dropdown.configure(width=15)
label = tk.Label(root, text="")
dropdown.pack(side = "top")
label.pack(side="top", fill="x", pady=10)
root.mainloop()
All of that being said, an OptionMenu is just a Menubutton and a `Menu. You can create your own widgets and directly assign functions to the items in the dropdown list.
Here's an example:
import tkinter as tk
def func1():
label.configure(text="func1 called")
def func2():
label.configure(text="func2 called")
root = tk.Tk()
root.geometry("400x200")
dropdown = tk.Menubutton(root, text="Choose a function", indicatoron=True, width=15)
dropdown_menu = tk.Menu(dropdown)
dropdown.configure(menu=dropdown_menu)
dropdown_menu.add_command(label="function 1", command=func1)
dropdown_menu.add_command(label="function 2", command=func2)
label = tk.Label(root, text="")
dropdown.pack(side = "top")
label.pack(side="top", fill="x", pady=10)
root.mainloop()
Note that the above example never changes the label that appears on the menu button. You can add code to do that if you wish. I left it out to keep the example simple.

Can Tkinter OptionMenu have variable size and options?

I am connecting to an email server and getting the number and names of 'folders' that are currently in use. Is it possible for *values (from tutorial code (1)) to be a list of StringVar objects? I have a list of StringVar objects that I want to dynamically update into the OptionMenu based on input from a server. So I am adding a dynamic list of StringVar objects and then trying to have them populate in the OptionMenu. I think the problem is that StringVar are objects and not text values, which is why it's not populating the OptionMenu. Is there a way to fix this?
Tutorial Code (1):
from Tkinter import *
# the constructor syntax is:
# OptionMenu(master, variable, *values)
OPTIONS = [
"egg",
"bunny",
"chicken"
]
master = Tk()
variable = StringVar(master)
variable.set(OPTIONS[0]) # default value
w = apply(OptionMenu, (master, variable) + tuple(OPTIONS))
w.pack()
mainloop()
Populating a list of StringVar objects (from another tutorial):
if resp == 'OK':
for mbox in data:
flags, separator, name = self.parse_mailbox(bytes.decode(mbox))
fmt = '{0} : [Flags = {1}; Separator = {2}'
fmt = '{0}'
if not "/ [Gmail]" in fmt.format(name):
temp = tk.StringVar()
temp.set(fmt.format(name))
self.list.append(temp)
Adding to OptionMenu Code:
variable = tk.StringVar(self)
variable.set("INBOX") #defaultvalue
tk.Label(self, text="Choose Mailbox: ").grid(row=1,sticky='W',padx=30,pady=10, columnspan=1)
self.mailboxes = tk.OptionMenu(self, variable, *self.controller.list)
#self.mailboxes = apply(OptionMenu, (self, variable) + tuple(self.controller.list))
self.mailboxes.grid(row=1,column=1,sticky='W',pady=10, columnspan=1)
Thank you for reading.
Edit Updated 'append' code to get StringVar() value and place into list
if not "/ [Gmail]" in fmt.format(name):
temp = tk.StringVar()
temp.set(fmt.format(name))
self.list.append(temp.get())
Also updated OptionMenu initilization
self.mailboxes = tk.OptionMenu(self, self.variable, *self.controller.list)
Here is the error message:
[1]: https://i.stack.imgur.com/a1Uye.png

How to swap values in optionmenu tkinter python?

How can i change values ​​in optionmenu when i press the "change" button?
Here is the code that I wrote so far:
import tkinter as tk
root = tk.Tk()
options =[
"eggs","meat","chicken",
"potato"
]
variable1 = tk.StringVar()
variable1.set(options[0])
om1 = tk.OptionMenu(root,variable1,*options)
om1.pack()
variable2 = tk.StringVar()
variable2.set(options[0])
om2 = tk.OptionMenu(root,variable2,*options)
om2.pack()
button_change = tk.Button(root,text="change")
button_change.pack()
root.mainloop()
please help...
You can swap the values of the two OptionMenu via their associated variables:
def swap_options():
# save the value of first OptionMenu
opt1 = variable1.get()
# set the value of first OptionMenu to that of second OptionMenu
variable1.set(variable2.get())
# set the value of second OptionMenu to the saved value of first OptionMenu
variable2.set(opt1)
button_change = tk.Button(root, text="change", command=swap_options)

Tkinter remove/overwrite elements from Frame

I created a button that retrieves a list from a DataFrame based on some input from a text field. Everytime the button is pressed, the list will be refreshed. I output the list (as an OptionMenu) in a separate Frame (outputFrame). However, every time I press this button, a new OptionMenu is added to the Frame (instead of overwriting the previous one). How can I make sure that the content of 'ouputFrame' is overwritten each time I press the button?
# start
root = Tkinter.Tk()
# frames
searchBoxClientFrame = Tkinter.Frame(root).pack()
searchButtonFrame = Tkinter.Frame(root).pack()
outputFrame = Tkinter.Frame(root).pack()
# text field
searchBoxClient = Tkinter.Text(searchBoxClientFrame, height=1, width=30).pack()
# function when button is pressed
def getOutput():
outputFrame.pack_forget()
outputFrame.pack()
clientSearch = str(searchBoxClient.get(1.0, Tkinter.END))[:-1]
# retrieve list of clients based on search query
clientsFound = [s for s in df.groupby('clients').count().index.values if clientSearch.lower() in s.lower()]
clientSelected = applicationui.Tkinter.StringVar(root)
if len(clientsFound) > 0:
clientSelected.set(clientsFound[0])
Tkinter.OptionMenu(outputFrame, clientSelected, *clientsFound).pack()
else:
Tkinter.Label(outputFrame, text='Client not found!').pack()
Tkinter.Button(searchButtonFrame, text='Search', command=getOutput).pack()
root.mainloop()
We can actually update the value of the OptionMenu itself rather than destroying it (or it's parent) and then redrawing it. Credit to this answer for the below snippet:
import tkinter as tk
root = tk.Tk()
var = tk.StringVar(root)
choice = [1, 2, 3]
var.set(choice[0])
option = tk.OptionMenu(root, var, *choice)
option.pack()
def command():
option['menu'].delete(0, 'end')
for i in range(len(choice)):
choice[i] += 1
option['menu'].add_command(label=choice[i], command=tk._setit(var, choice[i]))
var.set(choice[0])
button = tk.Button(root, text="Ok", command=command)
button.pack()
root.mainloop()

Categories

Resources