我正在编写一个脚本,可以搜索配方及其成分的列表。我想要一个类似google搜索框的东西,在键入时会给出一个下拉列表(这样用户可以看到成分并且没有错字)。我为此使用了组合框,但是我需要支持多种成分搜索,并且从组合框中进行选择会覆盖整个框(而不是部分框)。从组合框中选择时,我也无法键入。我可以使用任何命令来解决这些问题,还是必须覆盖脚本中的某些默认方法?如果是这样,请告诉我该怎么做。
我谦虚地接受我的代码的任何建议或批评。
感谢您抽出宝贵的时间阅读我的代码,并帮助我提出解决方案。
'__init__
'包括窗口的所有内容,update_combo用于更新组合框的值,searchall和searchavailability只是该应用程序的功能,与上述问题无关。 count_drinks与上面的问题也不相关。
from collections import defaultdict
from tkinter.ttk import Combobox
from tkinter import *
class CapitalBartending:
def __init__(self):
self.mainwindow = Tk()
self.mainwindow.maxsize(width=1100, height=800)
self.mainwindow.title("Capital Bartending School")
self.mainwindow.focus_set()
self.searchframe = Frame(width=1000, height=180)
self.resultframe = Frame()
self.quitbutton = Frame()
self.liquormsg1 = StringVar()
self.liquormsg2 = StringVar()
self.titlelabel = Label(self.searchframe, text="\nSearch Recipe", font=("", 20, "bold"))
self.titlelabel.place(relx=0.5, rely=0.18, anchor=CENTER)
# search and entry box
self.searchlabel = Label(self.searchframe, text='Search: ')
self.searchlabel.place(relx=0.36, rely=0.52, anchor=W)
self.searchenter = Combobox(self.searchframe, width=60, postcommand=self.update_combo)
self.searchenter.bind("<KeyRelease>", self.searchall)
self.searchenter.place(relx=0.574, rely=0.52, anchor=CENTER)
# availabile search and entry box
self.availabilelabel = Label(self.searchframe, text='Available Liquor: ')
self.availabilelabel.place(relx=0.314, rely=0.63, anchor=W)
self.availabileenter = Combobox(self.searchframe, width=60, postcommand=self.update_combo)
self.availabileenter.bind("<KeyRelease>", self.searchavailability)
self.availabileenter.place(relx=0.574, rely=0.63, anchor=CENTER)
# result label
self.resultlabel = Label(self.searchframe, text='\nResults', font=("", 15))
self.resultlabel.place(relx=0.499, rely=0.85, anchor=CENTER)
# results
self.showresult = Text(self.resultframe, font=("Calibri", 12), width=500)
self.resultscroll = Scrollbar()
self.showresult.pack(side='top')
self.resultscroll.pack(side='right', fill=Y)
self.resultscroll.config(command=self.showresult.yview)
self.showresult.config(yscrollcommand=self.resultscroll.set)
self.showresult.tag_config('center', justify='center')
# destroy button
self.end_button = Button(self.quitbutton, text='Quit', command=self.mainwindow.destroy, width=10)
self.end_button.pack(side='bottom')
# pack
self.searchframe.pack(fill=X)
self.resultframe.pack(expand=True)
self.quitbutton.pack()
# break until button
self.mainwindow.mainloop()
def searchall(self, event):
self.showresult.delete(1.0, END)
nameresultindex = [0] * 152
alcoholresultindex = [1] * 152
searchin = self.searchenter.get().lower().strip(",")
if searchin == 'count_drinks()':
self.count_drinks()
for index, item in enumerate(name):
if searchin.upper() in item:
nameresultindex[index] = 1
searchin = searchin.split(" ")
if "" in searchin:
searchin.pop()
for i in range(len(searchin)):
for j in range(len(procedure)):
if searchin[i] not in procedure[j].lower():
alcoholresultindex[j] = 0
if alcoholresultindex[j] == 1:
if searchin[i] not in procedure[j].lower():
alcoholresultindex[j] = 0
else:
pass
for i in range(len(nameresultindex)):
if nameresultindex[i] == alcoholresultindex[i] == 1:
alcoholresultindex[i] = 0
if searchin:
for i in range(len(nameresultindex)):
if nameresultindex[i] == 1:
result = "\n" + name[i] + ': ' + procedure[i].replace("-", " ") + "\n"
self.showresult.insert(INSERT, result, 'center')
if alcoholresultindex[i] == 1:
result = "\n" + name[i] + ': ' + procedure[i].replace("-", " ") + "\n"
self.showresult.insert(INSERT, result, 'center')
def searchavailability(self, event):
self.showresult.delete(1.0, END)
resultindex = [0] * 152
availabledrink = []
availablenamein = self.availabileenter.get().title()
availablenamein = availablenamein.split(",") if ',' in availablenamein else availablenamein.split(" ")
if "" in availablenamein:
availablenamein.pop()
for item in availablenamein:
for index, item2 in enumerate(used_alcohol):
if item.replace(" ", "-") == item2.title():
availabledrink.append(index)
availabledrink = list(set(availabledrink))
for i in range(len(alcohol_in_drink)):
for j in range(len(alcohol_in_drink[i])):
if alcohol_in_drink[i][j] not in availabledrink:
break
if alcohol_in_drink[i][j] == alcohol_in_drink[i][-1]:
resultindex[i] = 1
if availabledrink:
for index, item in enumerate(resultindex):
if item == 1:
result = "\n" + name[index] + ': ' + procedure[index].replace("-", " ") + "\n"
self.showresult.insert(INSERT, result, 'center')
def update_combo(self):
# I want to update value list in combo box as user type in more characters
suggestion = []
# I have two combo box and need to get value from whichever one that's not empty
suggestin = self.searchenter.get().title()
suggestin = self.availabileenter.get().title() if suggestin == "" else suggestin
# ',' is used when doing multi-ingredient search
suggestin = suggestin.split(",") if ',' in suggestin else suggestin.split(" ")
suggestin = [item.strip(' ') for item in suggestin]
try:
suggestin = suggestin.remove(" ")
except ValueError:
pass
[suggestion.append(item) for item in used_alcohol if suggestin[-1] in item]
suggestion.sort()
self.searchenter['values'] = suggestion
print(suggestion, suggestin)
def count_drinks(self):
not_liquor = ['Shake', 'Juice', 'Mix', 'Sour', 'Cream', 'Soda', 'Melon', 'Liqueur', 'Cherry', 'Water', 'Sugar',
'Dark', 'Light', 'Salt', 'Coke', 'Ginger', 'Red', 'Bull', 'Orange']
count_liquors = defaultdict(lambda: 0)
for item in procedure:
line = item.replace(',', '').replace("'", '').replace('(', '').replace(')', '').replace('=', '').split(' ')
for item1 in line:
count_liquors[item1] += 1 if item1.istitle() and item1 not in not_liquor else 0
count_liquors = [(key, count_liquors[key]) for key in count_liquors.keys()]
count_liquors.sort(key=lambda item: item[1], reverse=True)
while True:
if 0 in count_liquors[-1]:
count_liquors.pop()
else:
break
with open('used_alcohol_ver_2.txt', 'w') as outfile:
[outfile.write(item[0] + ' ' + str(item[1]) + '\n') for item in count_liquors]
if __name__ == '__main__':
with open('recipe.txt', 'r') as filein:
recipein = filein.read().split('\n')
with open('used_alcohol.txt', 'r') as filein:
alcoholin = filein.read().split('\n')
name = []
procedure = []
used_alcohol = []
alcohol_in_drink = []
# construct name and procedure list
[(name.append(item[:item.index('|')]), procedure.append(item[item.index('|') + 1:])) for item in recipein]
[used_alcohol.append(item.split(' ')[0]) for item in alcoholin]
# construct a list for alcohol used in each recipe
for index, item in enumerate(procedure):
line = item.replace(",", "").split(" ")
alcohol_in_drink.append([])
for index2, item2 in enumerate(used_alcohol):
if item2 in line:
alcohol_in_drink[index].append(index2)
CapitalBartending()