你不能给它添加滚动条,但是I have coded something similar to this。这是一种 hacky 方式,可能很难理解,但我可以尝试解释一下。
注意正如 Bryan 在链接线程中提到的,这似乎是一个仅限 Windows 的解决方案。
import tkinter as tk
def my_first_function():
print('first')
def my_second_function():
print('second')
def check_for_scroll(event):
check = root.call(event.widget, "index","active")
if check == 0: #index of button up
scroll_up()
root.after(100,lambda e=event:check_for_scroll(e)) # check again after 100ms
if check == file_menu.index('end'):
scroll_down()
root.after(100,lambda e=event:check_for_scroll(e))
def scroll_up():
index_of_first_command=1
index_of_last_command=1
label_of_last_command = file_menu.entrycget(index_of_first_command, 'label')
try:
for i, k in enumerate(dict_of_commands):
if k == label_of_last_command:
previous_command_label = list(dict_of_commands)[i-1]
previous_command = list(dict_of_commands.values())[i-1]
if i != 0: #avoid to get the last as first
file_menu.delete(index_of_first_command) #first before pull down button
file_menu.insert_command(index_of_first_command,
label=previous_command_label,
command=previous_command)
except Exception as e:
print(e)
def scroll_down():
index_of_first_command=1
index_of_last_command=1
label_of_last_command = file_menu.entrycget(index_of_last_command, 'label')
try:
for i, k in enumerate(dict_of_commands):
if k == label_of_last_command:
next_command_label = list(dict_of_commands)[i+1]
next_command = list(dict_of_commands.values())[i+1]
file_menu.delete(index_of_first_command) #first after pull up button
file_menu.insert_command(index_of_last_command,
label=next_command_label,
command=next_command)
except:
pass
space = ' '
dict_of_commands = {'first' : my_first_function,
'second': my_second_function}
root = tk.Tk()
menubar = tk.Menu(root)
root.config(menu=menubar)
file_menu = tk.Menu(menubar,tearoff=0)
menubar.add_cascade(label='File', menu=file_menu)
file_menu.bind('<<MenuSelect>>', check_for_scroll)
file_menu.add_command(label=space+u'\u25B2'+space, font=["Arial", 8,'bold'])
file_menu.add_command(label='first', command=my_first_function)
file_menu.add_command(label=space+u'\u25BC'+space, font=["Arial", 8,'bold'])
root.mainloop()
所以这段代码会创建你的窗口和一个菜单栏:
root = tk.Tk()
menubar = tk.Menu(root)
root.config(menu=menubar)
file_menu = tk.Menu(menubar,tearoff=0)
menubar.add_cascade(label='File', menu=file_menu)
file_menu.add_command(label=space+u'\u25B2'+space, font=["Arial", 8,'bold'])
file_menu.add_command(label='first', command=my_first_function)
file_menu.add_command(label=space+u'\u25BC'+space, font=["Arial", 8,'bold'])
root.mainloop()
对你很重要,这行在这里吗:
file_menu.bind('<<MenuSelect>>', check_for_scroll)
此行绑定事件 MenuSelect,如果您的光标悬停在菜单命令上,它就会发生/触发。对于这个事件,我绑定了一个名为 check_for_scroll 的函数,它看起来像这样:
def check_for_scroll(event):
check = root.call(event.widget, "index","active")
if check == 0: #index of button up
scroll_up()
root.after(100,lambda e=event:check_for_scroll(e)) # check again after 100ms
if check == file_menu.index('end'):
scroll_down()
root.after(100,lambda e=event:check_for_scroll(e))
下面的行检查触发事件的命令的索引。通过这个,我们用箭头检查我们感兴趣的按钮是第一个还是最后一个。
check = root.call(event.widget, "index","active")
如果它是第一个例如这里的代码被执行:
if check == 0: #index of button up
scroll_up()
root.after(100,lambda e=event:check_for_scroll(e)) # check again after 100ms
它调用/触发函数 scroll_up 然后使用 tkinter 的 after 方法重新触发自身,就像循环一样。 scroll_up 函数的构建方式与 scroll_down 类似,只是在相反的方向上。让我们仔细看看:
def scroll_up():
index_of_first_command=1
index_of_last_command=1
label_of_last_command = file_menu.entrycget(index_of_first_command, 'label')
try:
for i, k in enumerate(dict_of_commands):
if k == label_of_last_command:
previous_command_label = list(dict_of_commands)[i-1]
previous_command = list(dict_of_commands.values())[i-1]
if i != 0: #avoid to get the last as first
file_menu.delete(index_of_first_command) #first before pull down button
file_menu.insert_command(index_of_first_command,
label=previous_command_label,
command=previous_command)
except Exception as e:
print(e)
在这个函数中,我们需要知道命令的第一个和最后一个位置,因为我们想删除一个并在该位置/索引上插入另一个。为此,我创建了一个字典,其中包含标签和 tkinter 命令项的功能,如下所示。 (这可以动态创建,但让我们保留另一个问题)
dict_of_commands = {'first' : my_first_function,
'second': my_second_function}
所以我们在函数中遍历这个 enumerated/indexed 字典并检查 k/key/label em> 是我们感兴趣的项目。如果为真,我们通过列出字典键获取previous_command,并通过以下行获取提取键之前的键:
next_command_label = list(dict_of_commands)[i+1]
类似字典的值有这行:
next_command = list(dict_of_commands.values())[i+1]
毕竟我们可以删除一个并在我们喜欢的地方插入一个:
file_menu.delete(index_of_first_command) #first after pull up button
file_menu.insert_command(index_of_last_command,
label=next_command_label,
command=next_command)
我知道这段代码可以改进很多,但它似乎很难理解。所以请不要评判我。
我希望这能解决您的问题,即使它不是您想要的方式。但是这段代码避免了你几乎编写自己的菜单栏。
如果我的回答还有问题,请告诉我。