Я создаю приложение Tkinter, которое должно создать серию комбинированных списков и заполнить их элементами из базы данных Sqlite. Однако даже после заполнения свойства values для каждого выпадающего списка невозможно отобразить раскрывающееся меню или иным образом взаимодействовать с полем после фактического запуска приложения.
Я могу предварительно установить индекс Combobox.current ()запустить основной цикл и, таким образом, отобразить значение по этому индексу, но как только основной цикл запустится, вообще не будет возможности взаимодействовать с блоком. Я попытался использовать обратный вызов после команды для заполнения списка, но получил тот же результат. Я не получаю ошибок во время процесса.
Примечание: в следующем коде есть пример данных, закодированных для замены запросов к БД. Это не меняет моих результатов.
from tkinter import *
import tkinter.ttk as ttk
class PCFrame(Frame):
def __init__(self, master):
self.master = master
super().__init__(master=master)
self.columnconfigure(0, minsize=100, weight=1)
self.columnconfigure(1, minsize=300, weight=3)
self.grid()
self.widgets = {}
self.pc_fieldnames = ["computer name",
"customer name",
"serial",
"model"]
self.init_ui()
def init_ui(self):
label_opts = {"column": 0, "sticky": W}
field_opts = {"column": 1, "sticky": E + W}
for rownum, i in enumerate(self.pc_fieldnames):
#Callback for postcommand that didn't change my results
def field_display_handler(self=self, fieldname=i):
return self.field_display(fieldname)
self.widgets[i] = {}
self.widgets[i]["NewValue"] = StringVar(self,
value=None)
#Values here are in the form (row_value, row_serial_num)
#Combobox will always display the first item in
#each of the tuples
self.widgets[i]["ValueTuples"] = []
self.widgets[i]["Field"] = ttk.Combobox(self, class_="PCField",
textvariable=self.widgets[i]["NewValue"],
state = "normal",
postcommand = field_display_handler,
values = [])
self.widgets[i]["Field"].rowname = i
self.widgets[i]["Field"].grid(row=rownum, **field_opts)
self.widgets[i]["Label"] = ttk.Label(self, text=i.capitalize())
self.widgets[i]["Label"].rowname = i
self.widgets[i]["Label"].grid(row=rownum, **label_opts)
self.populate()
for i in self.pc_fieldnames:
self.field_display(i)
self.widgets[i]["Field"].current(newindex=0)
def populate(self, search_column = None, search_criteria = None,
rows=None):
if rows == None:
#Test values here, normally would use a DB query here
rows = []
for i in range(5):
rows.append({})
for j in self.pc_fieldnames:
rows[i][j] = j + " " + str(i)
#Reinitialize, then populate, all fields
for k, w in self.widgets.items():
w["ValueTuples"] = []
for row in rows:
for key in row.keys():
k = key.lower()
entry = row[k] if row[k] != None else ""
try:
self.widgets[k]["ValueTuples"].append(
(entry, row["serial"]))
except KeyError:
if k not in self.pc_fieldnames:
pass
else:
raise
def field_display(self, fieldname):
display = []
for i in self.widgets[fieldname]["ValueTuples"]:
display.append(i[0])
self.widgets[fieldname]["Field"]["values"] = display
if __name__ == "__main__":
root = Tk()
frame = PCFrame(root)
root.mainloop()