How to swap values in optionmenu tkinter python? - 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)

Related

Use loop to create x number of tkinter OptionMenu

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()

Is there a way for the Entry widget to not mimic the Checkbutton's value?

Right off the bat here is my code so far (please ignore the variable names. I am still learning how to use Python):
root = Tk()
testvariable = 0
bruh = 0
test = Checkbutton(root, variable = testvariable, )
test.pack()
test1 = Entry(root,textvariable = bruh, text = "0", width = 4)
test1.pack()
root.mainloop()
I notice that when I select the Checkbutton to turn it off or on, the Entry widget automatically changes its value to whatever the Checkbutton's value is. Is there a way to prevent this?
When setting variables in tkinter make sure to use the built-in types (https://docs.python.org/3/library/tkinter.html#coupling-widget-variables).
For the Entry widget you can directly use the get method to assign its value to a variable. As for the Checkbutton widget, make sure to assign it an "IntVar" type to correctly deal with its value passing. I've demonstrated how to do both of the above in the code below.
import tkinter as tk
root = tk.Tk()
checkbox_var = tk.IntVar()
testvariable = 0
bruh = 0
test = tk.Checkbutton(root, variable=checkbox_var)
test.pack()
test1 = tk.Entry(root)
test1.pack()
def testOutput():
testvariable = checkbox_var.get()
bruh = test1.get()
print("Checkbox is", testvariable)
print("Entry is", bruh)
button = tk.Button(root, text="Test Button", command=testOutput)
button.pack()
root.mainloop()
They mimic each other because both of their textvariable attributes are the same value. The short answer is to give them each different values for textvariable.
Also, you should be setting that attribute to an instance of a tkinter variable such as StringVar or IntVar. However you rarely need to use that attribute with Entry widgets, since the widget itself gives you methods for getting and setting the value.

How can I pass an argument to a function from a drop down in tkinter GUI

I have a function
def hist(x):
plotly.offline.plot( {
'data' : [{
'type' : 'histogram',
'x' : data[x],
}],
"layout": Layout(title=x)
})
hist("price")#function call
in place of price i want the user to select other options in drop-down of tkinter gui and it should get updated in function call how should i proceed.
and also how to set a background image for a tkinter window which fits all the window irrespective of the dimensions of the window.
This can be done using an OptionMenu widget from tkinter.
Essentially all we need to do is initialise the OptionMenu widget and then call it's StringVar variable.
from tkinter import *
root = Tk()
def command():
print(var.get())
var = StringVar(root)
var.set("Price")
option = OptionMenu(root, var, "Price", "Foo", "Bar")
option.pack()
button = Button(root, text="Ok", command=command)
button.pack()
root.mainloop()
The above will create an OptionMenu and a Button and print the value of the OptionMenu whenever the Button is pressed.
Once you understand the base concepts at play here you can start getting "fancy" with how your inputting information.
We can set up a trace on the StringVar variable and use it to detect when the OptionMenu is updated, meaning we get an automatic response in the program without the user having to press a button after selecting something from the drop down.
from tkinter import *
root = Tk()
def command(*args):
print(var.get())
var = StringVar(root)
var.set("Price")
option = OptionMenu(root, var, "Price", "Foo", "Bar")
option.pack()
var.trace("w", command)
root.mainloop()

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()

Linking Tkinter label based on Entry value

Is there a way to make a Tkinter label that automatically updates to reflect changes in the text of an Entry field? For example, if the Entry has the text "1", the label should say "T1", but if the user changes the text in entry to "x" then the label should say "Tx", without having to press a button.
Yes, this is possible. The easiest way I can think of is using the .trace method of a StringVar, which calls a function if the value of the StringVar() changes. Here's an example:
def change_label(*args):
label.config(text='') # clear label
label.config(text='T' + var.get()) # set new label text
root = Tk()
var = StringVar() # make the StringVar()
label = Label(root)
entry = Entry(root, textvariable=var) # set the textvariable to var
var.trace('w', change_label) # trace var to monitor for changes, calling function on change
label.pack()
entry.pack()
root.mainloop()
More on trace: http://effbot.org/tkinterbook/variable.htm

Categories

Resources