琐事
这个技巧在 X Window 系统(读取为 Unix)中有效,因为“Alt-keying”由 tk 本身通过 tk::TraverseToMenu 函数处理,在这种情况下绑定到 all 绑定标签.
在您的情况下,tk 检测到它在Win 环境中工作,并将tk::TraverseToMenu 函数仅绑定到Menubutton 绑定标签,因为在这种情况下,“Alt-keying”由本机@处理987654333@wm。
menu.tcl中的源代码代表了所说的:
if {[tk windowingsystem] eq "x11"} {
bind all <Alt-KeyPress> {
tk::TraverseToMenu %W %A
}
bind all <F10> {
tk::FirstMenu %W
}
} else {
bind Menubutton <Alt-KeyPress> {
tk::TraverseToMenu %W %A
}
bind Menubutton <F10> {
tk::FirstMenu %W
}
}
解决方案
当您按下 Alt 键时,Windows sends a message,表示 the Alt-key is pressed down,并等待 for another message,其中包含指定字符作为 ANSI 代码。
接收到指定字符后,wm 正在尝试查找要打开的菜单。
同时tk::TraverseToMenu 运行良好 - 尝试将空字符串或任意字符作为char 参数传递,但找不到该菜单。仅当您尝试在 Windows 房屋附近的草坪上玩耍时才会出现此问题。
在这种情况下你最好的选择:SendMessage 或 keybd_event。
所以一个完整的黑客(正如@Donal Fellows 所说)是这样的:
import tkinter as tk
root = tk.Tk()
if root._windowingsystem == 'win32':
import ctypes
keybd_event = ctypes.windll.user32.keybd_event
alt_key = 0x12
key_up = 0x0002
def traverse_to_menu(key=''):
if key:
ansi_key = ord(key.upper())
# press alt + key
keybd_event(alt_key, 0, 0, 0)
keybd_event(ansi_key, 0, 0, 0)
# release alt + key
keybd_event(ansi_key, 0, key_up, 0)
keybd_event(alt_key, 0, key_up, 0)
else:
# root._windowingsystem == 'x11'
def traverse_to_menu(key=''):
root.tk.call('tk::TraverseToMenu', root, key)
menubar = tk.Menu(root)
sub1 = tk.Menu(menubar, tearoff=0)
sub1.add_command(label='Item 1', command=lambda: print('item 1'))
sub1.add_command(label='Item 2', command=lambda: print('item 2'))
menubar.add_cascade(menu=sub1, label='Sub1', underline=0)
root.config(menu=menubar)
traverse_button = tk.Button(root, text='Test', command=lambda: traverse_to_menu('S'))
traverse_button.pack()
root.mainloop()