在某些情况下(下面的演示),OpenMenu 小部件上显示的值与程序使用的值不匹配,这会导致当用户期望选项 A 时执行选项 B - 导致 WTF?用户的反应。
不幸的是,OptionMenu 小部件没有我与其他小部件一起使用来轻松处理问题的“命令”选项(例如演示中的“A_Button”小部件)。我尝试过使用绑定,但到目前为止我还没有解决问题的“灵丹妙药”。
我检查了常用的地方(NMT、effbot、这里等),发现这个小部件几乎没有有用的文档,特别是在处理下拉列表中的项目时。 (知道如何确定列表中的项目数,列表中当前选定值的位置/索引以及如何将小部件包含在 GUI 的选项卡序列中将会很有用)。
我的申请是多语言的;当语言改变显示值时andOptionMenu 小部件的下拉列表必须相应更改。 (顺便说一句,多语言意味着您不能在代码中直接使用 .get() 的结果,特别是在添加另一种语言的情况下。为了获得语言独立性,我使用通过将 .get() 值与值匹配而创建的索引在选项菜单中 - 有更好的方法吗?)
在演示代码中,所选语言决定 OptionMenu 小部件显示的值。 “使用日期”(按钮小部件)正是实际应用程序的启动方式(以及为什么强制 GUI 和程序值始终匹配 - 这并不总是发生)。相比之下,“今天是什么日子?” (也是一个按钮小部件)使用命令选项来实现预期/正确的行为 - 正如我的应用程序中多次成功完成的那样。
要查看问题,请运行演示,选择任意语言。在不改变语言的情况下,日子会多次改变。请注意,打印值(由我的应用程序使用)始终是 GUI 小部件上显示的值后面的一个选择。接下来,在不更改日期的情况下,选择不同的语言(将打印新语言)。 OptionMenu 下拉值不会更改,直到after鼠标离开 OptionMenu 小部件 - 及其显示的值never被“翻译”成新语言。
我忽略/遗漏/做错了什么?
from tkinter import Button, IntVar, Label, OptionMenu, Radiobutton, Tk, StringVar
# You can skip over this section, it's basic gruntwork needed to set up the demo (values used have no impact on the problem).
English = 0
French = 1
Spanish = 2
DayNumbers = 3
DefaultDay = 2 # Corresponds to Tuesday, emulates the user's choice of day (on the GUI)
DefaultLanguage = English
Languages = [ "English", "French", "Spanish", "Day Numbers" ] # for use on GUI
EnglishWeekdays = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ]
FrenchWeekdays = [ "dimanche", "lundi", "mardi", "mecredi", "jeudi", "vendredi", "samedi" ]
SpanishWeekdays = [ "domingo", "lunes", "martes", "miercoles", "jeuves", "viernes", "sabado" ]
NumberedWeekdays = [ "Day 0", "Day 1", "Day 2", "Day 3", "Day 4", "Day 5", "Day 6" ]
DayNames = [ EnglishWeekdays, FrenchWeekdays, SpanishWeekdays, NumberedWeekdays ]
# The variables
LanguageInUse = DefaultLanguage
Weekdays = DayNames[ LanguageInUse ]
Today = DefaultDay # Isolates application code from language on GUI
#-------------------------------------------------------------------------------
def ChooseLanguage( ParentFrame ) :
global LanguageInUse, DropdownMenu
GUI_Language = IntVar( value = LanguageInUse )
#---------------------------------------------------------------------------
def SwitchLanguage():
global LanguageInUse , Weekdays
LanguageInUse = GUI_Language.get()
print( "SwitchLanguage sets language index to", LanguageInUse, "(" + Languages[ LanguageInUse ] + ")" )
Weekdays = DayNames[ LanguageInUse ]
DropdownMenu[ 'menu' ][ 'title' ] = Weekdays[ Today ]
for i, DayName in enumerate( Weekdays ) :
DropdownMenu[ 'menu' ].entryconfig( i )['label' ] = DayName
return
#---------------------------------------------------------------------------
LanguageButton = []
for LanguageIndex, Language in enumerate( Languages ) :
LanguageButton = LanguageButton + [ Radiobutton( ParentFrame,
indicatoron = False, width = 12,
variable = GUI_Language, command = lambda: SwitchLanguage(),
text = Language, value = LanguageIndex ) ]
LanguageButton[ LanguageIndex ].grid( row = 0 , column = LanguageIndex )
return
#-------------------------------------------------------------------------------
def GetDayIndex() :
global Today, DropdownMenu
Today = 0
for Index, DayName in enumerate( Weekdays ) :
if ( GUI_Value.get() == DayName ) :
Today = Index
break
print( "GetDayIndex sets weekday index to", Today, "(" + Weekdays[ Today ] + ")" )
for i, j in enumerate( Weekdays ) :
DropdownMenu[ 'menu' ].entryconfig( i , label = j )
return
#-------------------------------------------------------------------------------
def DoSomethingUseful() :
print( " Program uses " + str( Today ) + " (" + Weekdays[ Today ] +")" )
return
#-------------------------------------------------------------------------------
# The mainline
root = Tk()
GUI_Value = StringVar( value = Weekdays[ Today ] )
Widget1 = Label( root, text = "Today is" )
Widget1.grid( row = 1, column = 0 )
DropdownMenu = OptionMenu( root, GUI_Value, *DayNames[ LanguageInUse ] ) # NOT in TAB key sequence !!!
DropdownMenu.grid( row = 1, column = 1 )
DropdownMenu.bind( "<Leave>", lambda _ : GetDayIndex() )
#OptionMenu_Configuration( DropdownMenu )
A_Button = Button( root, text = "What day is it??", command = lambda : GetDayIndex() )
B_Button = Button( root, text = "Use the date", command = lambda: DoSomethingUseful() )
A_Button.grid( row = 1, column = 2 )
B_Button.grid( row = 1, column = 3 )
ChooseLanguage( root ) # creates/manages the language choice widgets
root.mainloop()