Drop down button in Tkinter OptionMenu - python

I need to update my list when I click the button to drop down list:
How can I bind the button to some function?

The event you're looking for is Activate:
optmenu.bind('<Activate>', onactivate)
Your onactivate callback takes an Activate event, but you probably don't care about its attributes.
The second half of your problem is how to update the menu. To do this, you use the menu attribute, which is a Menu object, on which you can call delete and add and whatever else you want. So, for example:
def onactivate(evt):
menu = optmenu['menu']
menu.delete(0, tkinter.END)
menu.add_command(label='new choice 1')
menu.add_command(label='new choice 2')
menu.add_separator()
menu.add_command(label='new choice 3')
optvar.set('new choice 1')
(However, notice that, while setting the var at the end does cause that to become the new default selection, and does show up in the menu header, it doesn't cause the selected item to be highlighted if the cursor isn't over any of the menu items. If you want that, it's tricky, so hopefully you don't.)

'<Activate>' didn't work but i found '<Button-1>' and now it works.
optmenu.bind('<Button-1>', onactivate)
Thank you :)

Related

How to destroy a specific widget at once ? Tkinter

When i pressed the "Create New" button a submit button will be appear at the bottom. But whenever i choose the drop down value the submit button will be destroyed and a new button called "Update" will be shown. But the problem is that, when I repeatedly choose the drop down value and go back to "Create New" button, the "update" button can only be destroy once. Is it a way to find all the update button and destroy all at once ? Thanks
When i pressed create new button :
When i choose a few times of drop down list value and go back to "create new", the submit and update button is stacked together :
Code:
def submit():
deleteAllEntry()
global CreateJsonBtn, profilenameLbl, ProfileNameEntry
CreateJsonBtn = Button(jsonframe, text="Submit", command=submit, width=11)
CreateJsonBtn.place(x=370, y=540)
CreateNewJsonBtn.configure(state=DISABLED)
UpdateJsonBtn.destroy()
#Get value inside the dropdown value
def dropdown(choice):
if (jsonprofileName == ""):
tkMessageBox.showinfo("ERROR", "Fail to retrieve value. Try again later", icon="error")
else:
cursor = con.cursor()
cursor.execute("select * from json where jsonprofilename='" +options.get() + "'")
rows = cursor.fetchall()
deleteAllEntry()
global row
for row in rows:
insertAllEntry()
cursor.close()
try:
#Delete submit button when select existing value
CreateJsonBtn.destroy()
CreateNewJsonBtn.configure(state=NORMAL)
except:
pass
finally:
global UpdateJsonBtn
UpdateJsonBtn = Button(jsonframe, text="Update", command=submit, width=11)
UpdateJsonBtn.place(x=370, y=550)
Instead of destroying and creating buttons multiple times, you can configure them, check the example below
from tkinter import *
def foo():
print('called foo')
button.configure(text='bar',command=bar)
def bar():
print('called bar')
button.configure(text='foo',command=foo)
root=Tk()
button=Button(root,text='foo',command=foo)
button.pack()
root.mainloop()
config/configure is a universal widget method, you can use this refernece to learn more about them.
The reason you are currently facing the issue is that every time the dropdown is used, a new button "Update" is placed on top of the previous one (if one already exists). The UpdateJsonBtn holds the last assigned instance and hence deletes the topmost one, if there are buttons underlying, they will not be destroyed. I would not suggest the approach currently used by you.
In the question you stated if there is a way to get all the buttons that say "Update", you can do that using the following (again, I am not suggesting to use this in your case, but just to answer your question)
for widget in jsonframe.winfo_children():
if isinstance(widget,Button):
if widget['text']=='Update':
widget.destroy()
So I know that it should work with CreateJsonBtn.place_forget()
You can try that

How can I bind command to Entry box when it is in focus?

http://code.activestate.com/recipes/580770-combobox-autocomplete/
Working with the class above. As of right now, a drop down list only appears when you start typing in into the entry box, auto completing the word you're typing in.
How can i create a method that makes the full list appear when the entry box is in focus?
You can bind to the <FocusIn> event to call a function when the widget gains focus.
def do_something(event):
...
entry = tk.Entry(...)
entry.bind('<FocusIn>', do_something)

Tkinter Menubutton widget key binding to open Menu widget elements in same window

I have created a submenu inside a menu using Menubutton and Menu widgets:
from tkinter import *
root = Tk()
def f(event):
submenu.invoke(0)
mainmenu = Menubutton(root, text="Menu")
mainmenu.pack()
submenu = Menu(mainmenu)
mainmenu.config(menu=submenu)
submenu.add_command(label="Option 1")
submenu.add_command(label="Option 2")
Now I want to add a key binding to my menu:
mainmenu.bind("<Key>", f)
mainmenu.focus_set()
It works as charm: when I press a key, it opens up the submenu. But the problem is, the submenu is opened as a torn off toplevel window. But I want it to be opened in same window with menu. I added tearoff=0 into submenu (so it became like this:submenu = Menu(mainmenu, tearoff=0)). But now, it does not return anything. I'm trying to figure out why it doesn't. Maybe I'm doing something wrong... I have looked for a solution, but none of them solves the problem. All they tell is just adding a key binding that prints out something, however I want a key binding that kinda automatically clicks on a menu item, and it pops up the item elements, but not as a separate window (maybe it's called contextmenu?). I couldn't find any solution to this specific problem anywhere.
So how can I make it happen? Any help would be appreciated.
I think
def f(event):
submenu.post(mainmenu.winfo_rootx(),
mainmenu.winfo_rooty() + mainmenu.winfo_height())
does what you want, even with the tearoff=False option.

Tkinter listbox change highlighted item programmatically

I have a listbox in Tkinter and I would like to change the item selected programatically when the user presses a key button. I have the keyPressed method but how do I change the selection in the Listbox in my key pressed method?
Because listboxes allow for single vs. continuous vs. distinct selection, and also allow for an active element, this question is ambiguous. The docs explain all the different things you can do.
The selection_set method adds an item to the current selection. This may or may not unselect other items, depending on your selection mode.
If you want to guarantee that you always get just that one item selected no matter what, you can clear the selection with selection_clear(0, END), then selection_set that one item.
If you want to also make the selected item active, also call activate on the item after setting it.
To understand about different selection modes, and how active and selected interact, read the docs.
If you need ListboxSelect event to be also triggered, use below code:
# create
self.lst = tk.Listbox(container)
# place
self.lst.pack()
# set event handler
self.lst_emails.bind('<<ListboxSelect>>', self.on_lst_select)
# select first item
self.lst.selection_set(0)
# trigger event manually
self.on_lst_select()
# event handler
def on_lst_select(self, e = None):
# Note here that Tkinter passes an event object to handler
if len(self.lst.curselection()) == 0:
return
index = int(self.lst.curselection()[0])
value = self.lst.get(index)
print (f'new item selected: {(index, value)}')

Pass text to menu label in tkinter

I want to make the text under the selection, in variable 'a' to appear as a label of the menu.
Here is the code:
def popup(event):
a=t_start.get("sel.first", "sel.last")
menu.post(event.x_root, event.y_root)
return a
def insert_word():
pass
t_start.bind("<Button-3>", popup)
menu = Menu(root, tearoff=0)
menu.add_command(label="Set selection 1", command=set_selection_1)
menu.add_command(label="Set selection 2", command=set_selection_2)
menu.add_command(label="%s" %popup, command=set_selection_2)
Right now, all I get is function popup address.
If I try popup.a, I get an error, function has no attribute 'a'. How do I overcome this and get whatever is in 'a' to be printed as menu label?
Callback methods like popup are not supposed to return anything. Instead, you should manipulate the menu from inside the function.
Also, as suggested by Brian, you probably rather want to modify an existing entry in the menu, instead of adding a new one each time you click the button. In this case, create the entry outside the function (like you do now), but use some placeholder for the label.
def popup(event):
a = t_start.get("sel.first", "sel.last")
menu.post(event.x_root, event.y_root)
menu.add_command(label=a, command=set_selection_2) # add to menu
# menu.entryconfig(2, label=a) # modify existing entry
If you want to change the text on a menu, you must use the entryconfig method. For example, to change the text of the first item you would do:
menu.entryconfig(0, label=a)

Categories

Resources