Getting a dropdown menu to update based on a variable - python

I am attempting to create a database management system with the ability to delete accounts. I can get the drop down menu to display the current list of users, but I don't understand how to make it show the new list of users. The code for the dropdown menu is as follows:
import tkinter
from tkinter import *
tkwindow = Tk()
tkwindow.title
users = ['user1','user2','user3']
def callback(*args):
name = var.get()
print ('%s' % name)
users.remove(name)
print (users)
option.setitems(*users)
var = StringVar(tkwindow)
var.trace("w", callback)
option = OptionMenu(tkwindow, var, *users)
option.pack()
Thanks in advance.

Try using the Menu option of the OptionMenu. For example if you get the index of the name string, you can delete that from the OptionMenu using the code below.
def callback(*args):
name = var.get()
print ('%s' % name)
users.remove(name)
print (users)
menu = option['menu']
menu.delete(menu.index(name))

Related

Not able to get integer value from entry field

I was trying to create a stock managing program as follows:
import mysql.connector as mc
from tkinter import*
import time
from datetime import date
mycon=mc.connect(host="localhost",user="root",passwd="1234",database="stock_manager")
cursor=mycon.cursor()
global stock_name
global stock_unit_price
global stocks_bought
def add():
global stock_name
global stock_unit_price
global stocks_bought
stock_name_label=Label(root,text="Enter Stock Name")
stock_name_entry=Entry(root,width=50)
stock_unit_price_label=Label(root,text="Enter unit price of stock")
stock_unit_price_entry=Entry(root,width=50)
stocks_bought_label=Label(root,text="Enter number of stocks bought: ")
stocks_bought_entry=Entry(root,width=50)
stock_name=stock_name_entry.get()
stock_unit_price=int(float(stock_unit_price_entry.get()))
stocks_bought=int(stocks_bought_entry.get())
stock_name_label.grid(row=2,column=0)
stock_name_entry.grid(row=3,column=0)
stock_unit_price_label.grid(row=4,column=0)
stock_unit_price_entry.grid(row=5,column=0)
stocks_bought_label.grid(row=6,column=0)
stocks_bought_entry.grid(row=7,column=0)
submit_stock_button=Button(root,text="Submit",command=submit)
submit_stock_button.grid(row=8,column=1)
def submit():
global stock_name
global stock_unit_price
global stocks_bought
submitted_label=Label(root,text="Submitted!")
total_investment=(stock_unit_price)*(stocks_bought)
date=date.today()
cursor.execute("insert into
all_stocks values(%s,%s,%s,%s,%s)"%(stock_name,stock_unit_price,stocks_bought,total_investment,date))
submitted_label.grid(row=9,column=1)
root=Tk()
title_label=Label(root,text="All Investments")
add_stock_button=Button(root,text="Add Stock",command=add)
title_label.grid(row=0,column=1)
add_stock_button.grid(row=1,column=0)
root.mainloop()
So what this program is supposed to do is let the user add a stock by clicking the button "add stock". It then reveals the entry fields as given in the add() function defined at the top. After inputting all the information, the user clicks submit. The program then sends a query to update a mysql database with the given information.
My problem is that I need "stock_unit_price" as float and "stocks_bought" as int so that the query is successful. But it appears that the entry field is giving a string value.
I tried converting the string into int like:
int('5.0')
And even tried like:
int(float('5.0'))
But nothing works. Pls help
You are using it wrongly .You cant get and assign at same time. I will suggest you to use StringVar . Please check the snippet
import tkinter as tk
root=tk.Tk()
root.geometry("300x100")
sk=tk.StringVar()
sb=tk.StringVar()
def Add():
stock_entry=int(stock_unit_price_entry.get())
stock_bought=int(stocks_bought_entry.get())
print(stock_entry+stock_bought)
sk.set("")
sb.set("")
stock_name_label = tk.Label(root,text = 'Enter unit price of stock')
stock_unit_price_entry = tk.Entry(root,textvariable = sk)
stocks_bought_label = tk.Label(root,text = 'Enter number of stocks bought:', )
stocks_bought_entry=tk.Entry(root, textvariable = sb)
submit_stock_button=tk.Button(root,text = 'Submit', command = Add)
stock_name_label.grid(row=0,column=0)
stock_unit_price_entry.grid(row=0,column=1)
stocks_bought_label.grid(row=1,column=0)
stocks_bought_entry.grid(row=1,column=1)
submit_stock_button.grid(row=2,column=1)
root.mainloop()
You will get integer as output
Or if you want to go by your method, you have to store your get value which is converted into integer in another variable and then you can use it.
stock_unit_price_entry=Entry(root,width=50)
stocks_bought_entry=Entry(root,width=50)
stock_unit=int(stock_unit_price_entry.get())
stock_bought=int(stocks_bought_entry.get())
print(stock_unit)
print(stock_bought)
This will also produce same integer output

how does the Entry widget in tkinter work?

I'm still a beginner with Tkinter and I'm not quite sure how the Entry widget work. I can't seem to get the value I enter I tried binding the root window to this function but I can't figure out why it's not working.
def get_value(event):
current_obj = root.focus_get()
if (current_obj in entries):
text = current_obj.get()
data.append(text)
You can use get to get the value from the entry.
First you define the entry like this:
e = tk.Entry()
e.pack()
Then you can have a static function which gets the value of the entry by calling entry.get()
def get_entry_value(entry)
entry.get()
Alternatively, if you have multiple entries in your app which are all contained in some iterable:
def get_entries(self, event=None):
data = list()
for e in self.entries:
data.append(e.get())
return data

Python - tkinter how to use if statements with get function?

The title is not very easy to understand, I know, so let me explain it here.
Basically if I do
if variable.get() == "Select Website":
print("ok")
it will print out "ok", but if I change it from "Select Website" to "Fareham" as well as the option in the drop down box to "Fareham" it will not notice it changed. If I want it to notice it changed I would need to do a while loop, but that would stop the script running in the first place.
How can I make the script print out "ok" if variable is changed to "Fareham"?
Current Code:
import tkinter
sites = [
"Fareham",
"Hants",
"Southampton",
"Eastleigh",
"Havant",
"Gosport",
]
win = tkinter.Tk()
win.geometry("500x500")
variable = tkinter.StringVar(win)
variable.set("Select Website")
drop = tkinter.OptionMenu(win, variable, *sites)
drop.pack()
if variable.get() == "Fareham":
print("ok")
win.mainloop()
You can do this by associating a callback funtion to the drop down menu:
import tkinter
def your_callback(*args):
if args[0] == "Fareham":
print("ok")
sites = [
"Fareham",
"Hants",
"Southampton",
"Eastleigh",
"Havant",
"Gosport",
]
win = tkinter.Tk()
win.geometry("500x500")
variable = tkinter.StringVar(win)
variable.set("Select Website")
drop = tkinter.OptionMenu(win, variable, *sites, command = your_callback)
drop.pack()
win.mainloop()
Here's where some important info can be found:
http://effbot.org/tkinterbook/variable.htm
By setting an observer to the variable variable, it will check it everytime it changes.
def check(*args):
if variable.get() == 'Fareham':
print 'ok'
variable.trace(
'w', # 'w' checks when a variable is written (aka changed)
check # this is the function it should call when the variable is changed
)
Just put the code in place of your current if statement and it will work like a charm.

Python Tkinter - get selection on Radiobutton

I need to retrieve the value of Radiobutton clicked and then use this value .
What is the way to retrieve the value of a Radiobutton clicked ?
the code to setup the Radiobutton is:
radio_uno = Radiobutton(Main,text='Config1', value=1,variable = 1)
radio_uno.pack(anchor=W,side=TOP,padx=3,pady=3)
radio_due = Radiobutton(Main,text='Config2', value=2,variable =1)
radio_due.pack(anchor=W,side=TOP,padx=3,pady=3)
radio_tre = Radiobutton(Main,text='Config3', value=3,variable = 1)
radio_tre.pack(anchor=W,side=TOP,padx=3,pady=3)
This is one solution:
Create a tk.IntVar() to track which button was pressed. I'm assuming you did a from tkinter import *.
radio_var = IntVar()
You'll need to change the way you declared your buttons:
radio_uno = Radiobutton(Main,text='Config1', value=1,variable = radio_var)
radio_due = Radiobutton(Main,text='Config2', value=2,variable = radio_var)
radio_tre = Radiobutton(Main,text='Config3', value=3,variable = radio_var)
Then use the get() method to view the value of radio_var:
which_button_is_selected = radio_var.get()
Then you can make an enum or just three if clauses that'll do stuff depending on which button is chosen:
if(which_button_is_selected == 1):
#button1 code
elif(which_button_is_selected == 2):
#button2 code
else(which_button_is_selected == 3):
#button3 code

Python Tkinter / How to let OptionMenus share one item list?

i'm trying to build multiple option menus sharing the same "base item list". A multiple selection of one item in different menus should not be possible, so all menus have to be updated when an item is selected in one of the available menus.
from tkinter import *
# for example 5 fields
number_of_fields = 5
starting_list = ["item1","item2","item3","item4","item5"]
entry_list = []
option_list = []
option_var = []
def quit():
raise SystemExit()
# if an item is selected in one of the
# menus run this function
def reset_menu(sel_item):
# for each field
for field in range(number_of_fields):
new_list = []
selection = option_var[field].get()
# look for selected items in all menus
# and build new list which contains all
# items from the starting_list minus the
# items which are already selected
# keep the one selected (for a menu itself)
for option in starting_list:
marker = 0
for j in range(number_of_fields):
if(str(option_var[j].get()) == str(option)):
marker = 1
if(marker == 0):
new_list.append(str(option))
else:
pass
if(str(selection) == str(option)):
new_list.append(str(option))
# print new generated item list
# just to be sure it works so far
print("field",field,"new list=",new_list)
# NOW HERE SOMETHING IS WRONG I GUESS
# empty menu
option_list[field]["menu"].delete(0, "end")
# add new menu items
for item in new_list:
option_list[field]['menu'].add_command(label=item, command=lambda value=item:option_var[field].set(value))
root = Tk()
root.title("OptionMenu")
# menu variable for each field
for i in range(number_of_fields):
option_var.append(StringVar(root))
# initial value for each field
for i in range(number_of_fields):
option_var[i].set("")
# create menu for each field
for i in range(number_of_fields):
option_list.append(OptionMenu(root, option_var[i], *starting_list, command=reset_menu))
# create entry for each field
for i in range(number_of_fields):
entry_list.append(Entry(root))
# build gui
for i in range(number_of_fields):
entry_list[i].grid(row=int(i),column=0,sticky=N+S+W+E)
option_list[i].grid(row=int(i), column=1,sticky=N+S+W+E)
button = Button(root, text="OK", command=quit)
button.grid(row=number_of_fields,column=1,sticky=N+S+W+E)
mainloop()
Now everthing seems to be fine until i try to update the menus. The new menu item lists are generated correctly (see print statement) and the menus have the right items, but after selected one menu, the only menu that changes its selected state is the last one. Any ideas?
Regards Spot
I found your question because I too was trying to complete the same task. After doing a bit of poking around in dir(tkinter), I have found a solution, which you have inspired me to create an account to post.
I have left your original comments in the code for sections that I left unchanged.
First, your code for generating your options is unnecessarily cluttered. Instead of manually populating the list from empty, it seems cleaner to remove items from the full list.
You are currently using tkinter.OptionMenu(). If you instead use tkinter.ttk.OptionMenu(), it has a method called set_menu(*values) that takes any number of values as its arguments and sets the choices of that menu to be those arguments.
If you make the switch, there one thing to note - ttk's OptionMenu does not allow its default value to chosen in the dropdown, so it's recommended to make that value blank, as I have done in the declaration for starting_list.
In order to persist the blank option, I added an additional blank option, in order for it to be selectable. This way, if you mistakenly choose the wrong selection, you can revert your choice.
from tkinter import *
from tkinter.ttk import *
# for example 5 fields
number_of_fields = 5
starting_list = ["","item1","item2","item3","item4","item5"]
entry_list = []
option_list = []
option_var = []
def quit():
raise SystemExit()
# if an item is selected in one of the
# menus run this function
def reset_menu(sel_item):
# for each field
for field in range(number_of_fields):
new_list = [x for x in starting_list]
selection = option_var[field].get()
# look for selected items in all menus
# and build new list which contains all
# items from the starting_list minus the
# items which are already selected
# keep the one selected (for a menu itself)
for option in starting_list[1:6]:
#add selectable blank if option is selected
if (str(selection) == str(option)):
new_list.insert(0,"")
for j in range(number_of_fields):
if(str(selection) != str(option) and str(option_var[j].get()) == str(option)):
new_list.remove(option)
# print new generated item list
# just to be sure it works so far
print("field",field,"new list=",new_list)
#set new options
option_list[field].set_menu(*new_list)
root = Tk()
root.title("OptionMenu")
# menu variable for each field
for i in range(number_of_fields):
option_var.append(StringVar(root))
# initial value for each field
for i in range(number_of_fields):
option_var[i].set("")
# create menu for each field
for i in range(number_of_fields):
option_list.append(OptionMenu(root, option_var[i], *starting_list, command=reset_menu))
# create entry for each field
for i in range(number_of_fields):
entry_list.append(Entry(root))
# build gui
for i in range(number_of_fields):
entry_list[i].grid(row=int(i),column=0,sticky=N+S+W+E)
option_list[i].grid(row=int(i), column=1,sticky=N+S+W+E)
button = Button(root, text="OK", command=quit)
button.grid(row=number_of_fields,column=1,sticky=N+S+W+E)
mainloop()
Something you may want to look into is making your option generation a bit more efficient. Right now, for n options, you're looping through your menus n^2 times. I would suggest looking at passing the value that was just selected in the callback instead of searching each menu to see what was previously selected.
As an additional minor note, your "OK" button causes a crash. I'm not sure if that was intentional behavior, a quirk in my system, or something else.
I hope this helps!
its been a while and ive found a possible solution for my problem...here is the code:
from tkinter import *
from tkinter import _setit
# for example 5 fields
number_of_fields = 5
starting_list = ["choose","item1","item2","item3","item4","item5"]
entry_list = []
option_list = []
option_var = []
def quit():
raise SystemExit()
# print entry_field text and selected option_menu item
def output():
print("---------------------------------------")
for nr,item in enumerate(entry_list):
if(item.get() != ""):
print(item.get() + " --> " + option_var[nr].get())
print("---------------------------------------")
# if an item is selected in one of the
# menus run this function
def reset_menu(*some_args):
for field in range(number_of_fields):
new_list = []
selection = option_var[field].get()
for option in starting_list[1:]:
marker = 0
for j in range(number_of_fields):
if(str(option_var[j].get()) == "choose"):
continue
if(str(option_var[j].get()) == str(option)):
marker = 1
if(marker == 0):
new_list.append(str(option))
else:
pass
if(str(selection) == str(option)):
new_list.append(str(option))
option_list[field]["menu"].delete(0, "end")
option_list[field]["menu"].insert(0, "command", label="choose", command=_setit(option_var[field], "choose"))
# add new menu items
for i in range(len(new_list)):
option_list[field]["menu"].insert(i+1, "command", label=new_list[i], command=_setit(option_var[field], new_list[i]))
root = Tk()
root.title("OptionMenu")
# menu variable for each field
for i in range(number_of_fields):
option_var.append(StringVar(root))
# initial value for each field
for i in range(number_of_fields):
# set "choose" as default value
option_var[i].set("choose")
# trace each variable and call "reset_menu" function
# if variable change
option_var[i].trace("w", reset_menu)
# create menu for each field
for i in range(number_of_fields):
option_list.append(OptionMenu(root, option_var[i], *starting_list))
# create entry for each field
for i in range(number_of_fields):
entry_list.append(Entry(root))
entry_list[i].insert(0, "entry"+str(i))
# build gui
for i in range(number_of_fields):
entry_list[i].grid(row=int(i), column=0, sticky=N+S+W+E)
option_list[i].grid(row=int(i), column=1, sticky=N+S+W+E)
button1 = Button(root, text="OK", command=quit)
button2 = Button(root, text="PRINT", command=output)
button1.grid(row=number_of_fields, column=0, sticky=N+S+W+E)
button2.grid(row=number_of_fields, column=1, sticky=N+S+W+E)
mainloop()
This solution also runs under python 2.7, just change "from tkinter ..." to "from Tkinter ...".
Please take a look at the smarter solution sephirothrr has posted (see post above)!
Regards
Spot

Categories

Resources