【问题标题】:How to insert a scrollbar to a menu?如何在菜单中插入滚动条?
【发布时间】:2021-01-25 15:28:21
【问题描述】:

我想向 tkinter 中的菜单小部件添加另一个小部件,在本例中为缩放小部件。 现在我看到的唯一解决方案是创建一个新命令并使用缩放小部件打开一个新窗口或在其他地方创建缩放小部件。两者对我来说似乎都不太吸引人。

欢迎任何关于如何存档的想法:)

【问题讨论】:

  • 请编辑您的问题以包含您目前拥有的代码的最小示例。
  • 您可以添加命令、子菜单、分隔符、单选按钮或复选框。刻度不是菜单小部件的选项
  • 您不能在菜单中添加滚动条或比例尺或任何其他小部件。

标签: python tkinter widget


【解决方案1】:

你不能给它添加滚动条,但是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)

我知道这段代码可以改进很多,但它似乎很难理解。所以请不要评判我。

我希望这能解决您的问题,即使它不是您想要的方式。但是这段代码避免了你几乎编写自己的菜单栏。

如果我的回答还有问题,请告诉我。

【讨论】:

  • 非常感谢。这不是我的想法,但我可能会以这种方式工作。
  • 不客气 :) 我希望它能带来令人满意的解决方案。编写代码很有趣,感谢您的提问。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-27
相关资源
最近更新 更多