get value from event in an entrybox - python-3.x

#I want to put the selected item from combobox in the merk_entry. and the selected item from the listbox(omschrijving) in model_entry.
.get() or insert aren't working in this function.
I tried both of them. Also Comboboxselected.
I dont know how fix this.
Thanks in advance.
from tkinter import *
from tkinter.ttk import Combobox
window=Tk()
window.geometry("500x500")
wagenmerk=["BMW","Mercedes","Audi"]
Bmw=["Bmw 1 reeks","Bmw 5 reeks Berline","Bmw 7 reeks"]
Mercedes=["A-klasse","B-klasse","Eqc","C-klasse"]
Audi=["A1","A3","A4"]
def toon_info(evt):
teller=1
merk_info=automerk_entry.get()
print(merk_info)
if merk_info == "BMW":
omschrijving.delete(0,END)
for line in Bmw:
omschrijving.insert(teller,Bmw[teller-1])
teller+=1
elif merk_info=="Mercedes":
omschrijving.delete(0,END)
for line in Mercedes:
omschrijving.insert(teller,Mercedes[teller-1])
teller+=1
elif merk_info=="Audi":
omschrijving.delete(0,END)
for line in Audi:
omschrijving.insert(teller,Audi[teller-1])
teller+=1
automerk_text=Label(text="automerk")
merk_text=Label(text="merk")
model_text=Label(text="model")
prijs_text=Label(text="prijs")
automerk_text.place(x=15,y=70)
merk_text.place(x=280,y=100)
model_text.place(x=280,y=120)
prijs_text.place(x=280,y=140)
merk=StringVar()
model=StringVar()
prijs=StringVar()
merk_entry=Entry(textvariable=merk,width="25")
model_entry=Entry(textvariable=model,width="25")
prijs_entry=Entry(textvariable=prijs,width="25")
merk_entry.place(x=320,y=100)
model_entry.place(x=320,y=125)
prijs_entry.place(x=320,y=150)
automerk_entry=Combobox(window,values=wagenmerk,width=30)
automerk_entry.bind("<<ComboboxSelected>>",toon_info)
automerk_entry.place(x=70,y=70)
omschrijving=Listbox(window,width=30,height=10)
omschrijving.place(x=70,y=100)
#button
bereken=Button(window,text="toon",width="30",height="2",command=toon_info,bg="grey")
bereken.place(x=70,y=270)

You have not set the two Entry widgets to take the change in values. Your Comboboxselected works as expected. Do the following changes to reflect the selection of the Combobox widget and the Listbox widget to the 2 Entry widgets:
def toon_info(evt):
teller=1
merk_info=automerk_entry.get()
merk.set(merk_info) # set the StringVar variable (assigned to the merk_entry widget)
...
...
Bind the Listbox widget:
def set_item(evt):
model.set(omschrijving.get(omschrijving.curselection()[0]))
omschrijving.bind('<<ListboxSelect>>', set_item)
And lastly, the Button-bereken is not set to send or activate any event/evt. So the callback function (under the option command) has to be changed

This is how I fixed it.
def set_item(evt):
model_entry.delete(0,END)
cur_selection=omschrijving.curselection()
if len(cur_selection)>0:
model.set(omschrijving.get(cur_selection[0]))

Related

Run function when an item is selected from a dropdown

I have a dropdown in tkinter, that i have populated with some items.
OPTIONS = [0,1,2,3,4,5,6,7]
clicked = tk.StringVar()
clicked.set(OPTIONS[0]) # default value
drop = tk.OptionMenu(frame2, clicked, *OPTIONS)
drop.place(relx = 0.65, rely=0.25, relwidth=0.08, relheight=0.6)
However, when a user selects a value, i want other things to happen as well.
Like returning the value to a global variable, or making the state of a button normal, so it's visible again.
How can i run a function, when an item is selected, or when a different item is selected?
EDIT:
Following the suggestions of TheLizzard, i changed my code to this:
# this function is triggered, when a value is selected from the dropdown
def dropdown_selection():
global dropdown_value
dropdown_value = clicked.get()
print("You changed the selection. The new selection is %s." % dropdown_value)
button_single['state'] = 'normal'
OPTIONS = list(range(8))
clicked = tk.StringVar(master=frame2)
clicked.set(OPTIONS[0])
clicked.trace("w", dropdown_selection)
drop = tk.OptionMenu(frame2, clicked, *OPTIONS)
drop.place(relx = 0.65, rely=0.25, relwidth=0.08, relheight=0.6)
However, i get this error:
TypeError: dropdown_selection() takes 0 positional arguments but 3 were given
Try this:
import tkinter as tk
def changed(*args):
print("You changed the selection. The new selection is %s." % clicked.get())
root = tk.Tk()
OPTIONS = list(range(8))
clicked = tk.StringVar(master=root) # Always pass the `master` keyword argument
clicked.set(OPTIONS[0]) # default value
clicked.trace("w", changed)
drop = tk.OptionMenu(root, clicked, *OPTIONS)
drop.pack()
root.mainloop()
In tkinter you can add callbacks to variables like StringVar using <tkinter variable>.trace(mode, callback) for more info read this.
Also always pass in the master keyword argument to all tkinter widgets/variables. You did this with the OptionMenu (it's the first argument usually). But you didn't do it for the StringVar. If you always pass the master keyword argument, you can save yourself a headache.
Edit:
When tkinter calls the callback when the variable is changed it passes some arguments (I don't think they are useful) so make sure that the callback accepts them. Instead of having def callback() use def callback(*args).

Tkinter Listbox will not return selected element

The code is as follows:
import tkinter as tk
plc=tk.Tk()
choices=["A","B","C]
choicesvar=tk.StringVar(value=choices)
l=tk.Listbox(master=plc,listvariable=choicesvar)
l.pack()
selected=l.get(l.curselection())
plc.mainloop()
The idea is to get what element is currently selected. But all I'm getting is TclError: bad listbox index "": must be active, anchor, end, #x,y, or a number.
.curselections
returns an empty tuple if nothing is selected. You are trying to get the user-selected input even before the user selects anything.
one way to overcome this is to set the default selection to the first row using .selection_set(0)
...
l=tk.Listbox(master=plc,listvariable=choicesvar)
l.pack()
l.selection_set(0)
print(l.get(l.curselection()))
...
But since you want to get user selected row, bind the <ButtonRelease> to an event handler then get the selected rows. something as shown below.
import tkinter as tk
def handler(event):
print([l.get(index) for index in l.curselection()])
plc=tk.Tk()
choices=["A","B","C"]
choicesvar=tk.StringVar(value=choices)
l=tk.Listbox(master=plc,listvariable=choicesvar, selectmode=tk.MULTIPLE)
l.pack()
l.bind('<ButtonRelease>', handler)
plc.mainloop()

Is there a way to know when a tkinter ComboBox option is clicked?

In tkinter , Buttons have a parameter called command which causes some function to run whenever the button is clicked.
Is the same possible to do with the options of a tkinter Combobox ?
For example :
I have three options in the tkinter Combobox : #1 , #2 , #3
Now , As soon as #1 is or clicked , I want to print something like Options 1 Selected.
Is it possible to do ?
P.S , As #Atlas435 pointed out about getting the selected value from the tk.Combobox() , I really dont want the value of the Combobox() , what I am asking is that whether there is way to make Combobox options work like Buttons which when clicked , causes some function to execute.
Take a look at this example, which does what you are asking for:
from tkinter import *
from tkinter import ttk
root = Tk()
def select(event): #the function to get triggered each time you choose something
if c.get() == lst[0]: #if it is the first item
print('Option 1 is selected')
elif c.get() == lst[1]: #if it is the second item
print('Option 2 is selected')
else: #or if it is the third item
print('Option 3 is selected')
lst = ['#1','#2','#3'] #creating option list
c = ttk.Combobox(root,values=lst,state='readonly') #creating a combobox
c.current(0) #setting first element as the item to be showed
c.pack(padx=10,pady=10) #putting on screen
c.bind('<<ComboboxSelected>>',select) #the event that your looking for
root.mainloop()
Ive commented it to understand better, if any doubts or errors, do let me know

Is there a way to change a buttons colour when the button is made in a function?

I have made a button within a function and when the button is clicked a command is run to change the button color.
However this does not work as I get an error, but I need to create the button in the function.
It works when the button is defined outside the function and I assume the issue is that the data is forgotten after a function ends.
from tkinter import *
root = Tk()
def ColourChange(Letter):
NameButton.config(bg = "red")
def Change():
Letter = "a"
NameButton=Button(root, text = "This", command = lambda Letter = Letter:
ColourChange(Letter)
NameButton.pack()
Change()
When I click the button I would like the color of the background to change.
The actual error is
NameButton.config(bg="red") NameError: name 'NameButton' is not defined"
Set your global variable so it can be access by other function.Also move NameButton.pack() to new line after NameButton=Button(root,text="This",command=lambda Letter=Letter: ColourChange(Letter)).
from tkinter import *
root=Tk()
def ColourChange(Letter):
NameButton.config(bg="red")
def Change():
global NameButton # global variable
Letter="a"
NameButton=Button(root,text="This",command=lambda Letter=Letter: ColourChange(Letter))
NameButton.pack()
#NameButton.pack()
Change()

Searching a tkinter dataframe

What I am attempting to create is a program that will first create a pandas dataframe. Then, it will make a tkinter window with an input entry frame, a button, and a text box. For the code I have below, when the button is pressed, I get an output that shows the header of the dataframe and the row that was "searched".
import pandas
from tkinter import *
#creates the dataframe
summer17=pandas.read_excel("summer17.xlsx","list")
window = Tk() #start of the main window
#function that will search the dataframe column "company" for any matches
def search_df():
search_result=summer17[summer17['Company'].str.contains("CAPS")]
t1.insert(END,search_result)
#Creates the entry box
e1_value=StringVar()
e1=Entry(window)
e1.grid(row=0,column=0)
#Creates a button
b1=Button(window,width=10,text='search',command=search_df)
b1.grid(row=0,column=1)
#Creates a text box
t1=Text(window,height=5,width=80)
t1.grid(row=0,column=2)
window.mainloop() #end of the main window
That works all and well, however, I want the user to be able to input a value into the entry box and press the button and search for that entry. So I change the function to be
def search_df():
search_result=summer17[summer17['Company'].str.contains(e1_value.get())]
t1.insert(END,search_result)
If I leave this blank, it returns the entire data frame (as I may or may not expect). However, if I put CAPS in the entry box and press the button, It still returns the entire dataframe.
My guess is that when I am getting the value from the entry box, there is a variable miss match, but I'm not sure how I would correct that.
i used one of my files to create the dataframe.
you need to add the e1_value to the entry by using the textvariable parameter.
I added a bind between the enter key and your function therefore you don't have to press the button, you can press the enter key instead. To do that, i used the bind function. This function binds a widget and a tkinter event. it executes the chosen function and passes a parameter (which is the event).
However the command paramter of the widget button does not pass any parameter when it executes the chosen function (the event is always a left clic). That's why your function takes *event as a parameter, event can be None. (i used *event but event=None works too, and i don't know which way is the most pythonic way, sorry)
PS : You should use import tkinter as tk because you may have some conflict with variable and function names if you use from tkinter import *
import pandas
import tkinter as tk
#creates the dataframe
summer17=pandas.read_csv("User_AD_Commun01_2017-07-26_15-01.csv",
sep=";",
encoding="latin1")
window = tk.Tk() #start of the main window
#function that will search the dataframe column "company" for any matches
def search_df(*event):
search_result=summer17.loc[summer17['company'].str.contains(e1_value.get(),
na=False, #ignore the cell's value is Nan
case=False)] #case insensitive
t1.insert(tk.END,search_result)
#Creates the entry box and link the e1_value to the variable
e1_value=tk.StringVar()
e1=tk.Entry(window, textvariable=e1_value)
e1.grid(row=0,column=0)
#execute the search_df function when you hit the "enter" key and put an event
#parameter
e1.bind("<Return>", search_df)
#Creates a button
b1=tk.Button(window,
width=10,
text='search',
command=search_df)
b1.grid(row=0,column=1)
#Creates a text box
t1=tk.Text(window,height=5,width=80)
t1.grid(row=0,column=2)
window.mainloop() #end of the main window

Resources