ttk.Combobox - 单击时不显示下拉框
ttk.Combobox - dropdown box not displaying when clicked
我正在制作一个 Tkinter 应用程序,它应该创建一系列组合框并使用来自 Sqlite 数据库的元素填充它们。但是,即使在为每个组合框填充值 属性 之后,也无法显示下拉菜单或在应用程序实际启动后以其他方式与该框进行交互。
我可以在启动主循环之前设置 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()
问题是您正在更改组合框的 class。这有效地删除了组合框的所有内置行为,因为默认绑定绑定到小部件的原始 class 名称。
您需要从组合框的定义中删除 class_="PCField"
,或者准备好添加您需要的所有绑定。
我正在制作一个 Tkinter 应用程序,它应该创建一系列组合框并使用来自 Sqlite 数据库的元素填充它们。但是,即使在为每个组合框填充值 属性 之后,也无法显示下拉菜单或在应用程序实际启动后以其他方式与该框进行交互。
我可以在启动主循环之前设置 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()
问题是您正在更改组合框的 class。这有效地删除了组合框的所有内置行为,因为默认绑定绑定到小部件的原始 class 名称。
您需要从组合框的定义中删除 class_="PCField"
,或者准备好添加您需要的所有绑定。