Open Edm1795 opened 2 years ago
This script creates a dropdown menu which populates by a list using the "" command in front of the list -- drop= OptionMenu(win, menu, list1)
from tkinter import *
win = Tk()
win.geometry("715x250")
menu = StringVar() menu.set("Select Any Language")
list1 = ["C++", "Java","Python","JavaScript","Rust","GoLang"]
drop= OptionMenu(win, menu, *list1) drop.pack()
win.mainloop()
Proper Solution
Use a Menu (rather than an OptionMenu), use add_command and use lamda in the function call. Without lamda the function call will be called instantly on creation of the command. But also store the variable needed (searchTerm) into a new variable directly inside of the lambda function:
def displaySelected(searchTerm):
# Gets item clicked on in menu then updates the screen to those corresponding results
print('function call initiated by clicking:', searchTerm)
indexOfSearchTerm = self.searchTermsCache.index(searchTerm)
self.clearTextFields()
self.updateResults(self.resultsCache[indexOfSearchTerm])
# print('Search term sent from Menu History:')
# print(self.searchTermsCache.index(searchTerm))
self.history1.delete(0, "end") # clear history list before reposting new terms, otherwise duplicates show
for searchTerm in self.searchTermsCache: # Populate Search History list from cache
self.history1.add_command(label=searchTerm, command=lambda x=searchTerm: displaySelected(x))
Note the command=lambda x=searchTerm: displaySelected(x))
contains x = searchTerm, then the function call takes x so that the proper searchTerm is saved into each instance of the search history.
Option Menu
def displaySelected(choice):
# Gets item clicked on in menu then updates the screen to those corresponding results
choice = variable.get()
indexOfSearchTerm = self.searchTermsCache.index(choice)
self.clearTextFields()
self.updateResults(self.resultsCache[indexOfSearchTerm])
print(choice)
print(self.searchTermsCache.index(choice))
# setting variable for Integers
self.master.option_add('*tearOff', FALSE)
variable = StringVar()
variable.set(' ')
self.searchTermsCache = [1,2,3,4]
# creating widget
self.dropdown = OptionMenu(
self.master,
variable,
*self.searchTermsCache,
command=displaySelected
)
self.dropdown.grid(row=0, column=2)
#for item in self.searchTermsCache: # populate drop down menu with items stored in searchTermsCache
# dropDownMenu.add_command(label=item, command=get)
Code Example of lambda with stored variable inside the lambda function:
import tkinter as tk
def f(x):
print(x)
root = tk.Tk()
menubar = tk.Menu(root)
root.configure(menu=menubar)
menu = tk.Menu(menubar, tearoff=False)
l = ['one', 'two', 'three']
for i in l:
menu.add_command(label=i, command=lambda x=i: f(x))
menubar.add_cascade(label='File', menu=menu)
root.mainloop()
Another Method for Solving the Scope Problem:
What you need to do is introduce a new level of scope, with a new binding, for each of the items. The easiest way to do that is to wrap it in a new function definition:
for item in items:
def item_command(name):
def new_command():
print(name)
return new_command
map[item] = item_command(item)
Cache all results into a list of lists which the button can access. Each list will be referenced by the search term used for it. Clicking on any item will load up those results directly into the interface, by passing a rerun of searching the catalogue.