这是我的问题的后续。我试着用ttk。OptionMenu增强下拉菜单的外观和感觉。但正如在这里的帖子中所指出的,"一个ttk选项菜单小部件开始时,它的所有值都在下拉菜单中。一旦选择了任何值,列表中的第一个值就会消失,永远不会再出现……"在那篇文章中建议的解决方法是在列表中添加一个空项。在我的例子中,由于我使用的是字典,所以将'':[]
添加为字典中的第一项可以解决这个问题。这是唯一的解决方案吗?我讨厌在我的字典里添加一个人工制品。下面是代码:
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
class App:
def __init__(self, master):
master.title("Continental System")
self.dict = {'':[], 'Asia': ['Japan', 'China', 'Malasia'],
'Europe': ['Germany', 'France', 'Switzerland'],
'Africa': ['Nigeria', 'Kenya', 'Ethiopia']}
self.frame1 = ttk.Frame(master)
self.frame1.pack()
self.frame2 = ttk.Frame(master)
self.frame2.pack()
self.variable_a = tk.StringVar()
self.variable_b = tk.StringVar()
self.variable_a.trace('w', self.updateoptions)
self.optionmenu_a = ttk.OptionMenu(self.frame1, self.variable_a, *self.dict.keys())
self.variable_a.set("Asia")
self.optionmenu_a.grid(row = 0, column = 0)
self.optionmenu_b = ttk.OptionMenu(self.frame1, self.variable_b, '')
self.optionmenu_b.grid(row = 0, column = 1)
self.btn = ttk.Button(self.frame2 , text="Submit", width=8, command=self.submit)
self.btn.grid(row=0, column=1, padx=20, pady=20)
def updateoptions(self, *args):
countries = self.dict[self.variable_a.get()]
self.variable_b.set(countries[0])
menu = self.optionmenu_b['menu']
menu.delete(0, 'end')
for country in countries:
menu.add_command(label=country, command=lambda country=country: self.variable_b.set(country))
def submit(self, *args):
var1 = self.variable_a.get()
var2 = self.variable_b.get()
if messagebox.askokcancel("Confirm Selection", "Confirm your selection: " + var1 + ' ' + var2 + ". Do you wish to continue?"):
print(var1, var2)
def set_window(self, *args):
w = 800
h = 500
ws = root.winfo_screenwidth()
hs = root.winfo_screenheight()
x = (ws/2) - (w/2)
y = (hs/2) - (h/2)
root.geometry('%dx%d+%d+%d' % (w, h, x, y))
root = tk.Tk()
app = App(root)
app.set_window()
root.mainloop()
我也得到了一些错误信息,包括AttributeError: 'App' object has no attribute 'optionmenu_b'
,这似乎已经在我上面的第一个问题的答案中得到了解决。
Exception in Tkinter callback
Traceback (most recent call last):
File "C:Python34libtkinter__init__.py", line 1487, in __call__
return self.func(*args)
File "C:Python34tk1_version2.py", line 32, in updateoptions
menu = self.optionmenu_b['menu']
AttributeError: 'App' object has no attribute 'optionmenu_b'
Python Version 3.4.1
你引用的那篇文章不正确。您不需要将空格作为列表中的第一项。ttk.OptionMenu
命令的签名需要默认值作为变量名后的第一个参数。
您不需要在字典中添加空项。需要在创建optionmenu时添加一个默认值:
self.optionmenu_a = ttk.OptionMenu(self.frame1, self.variable_a, "Asia", *self.dict.keys())
一个稍微好一点的解决方案是获取键列表并将它们保存到一个列表中。对列表进行排序,然后使用列表的第一个元素作为默认值:
options = sorted(self.dict.keys())
self.optionmenu_a = ttk.OptionMenu(self.frame1, self.variable_a, options[0], *options)
您得到错误的原因是因为您对调用引用self.optionmenu_b
的函数的变量进行了跟踪,但是您最初在创建self.optionmenu_b
之前设置了该变量。简单的解决方案是先创建第二个菜单。
self.optionmenu_b = ttk.OptionMenu(...)
self.optionmenu_a = ttk.OptionMenu(...)