You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Tkinter的Menubutton菜单内添加滚动条?

为Tkinter Menubutton的字体菜单添加滚动条

我正在开发一款可选择文本字体的Tkinter应用,主窗口中有一个Menubutton,内含约347种可选字体,希望为该菜单添加滚动条以方便浏览。以下是无滚动条的实现代码:

import tkinter as tk
from tkinter import Menu, FLAT

# 假设main_window已定义,font_nameX和fontX函数已实现
main_window = tk.Tk()

# Menu button
fonts_MenuButton = tk.Menubutton(main_window, text="v", bg="WHITE", fg="BLACK", activebackground="WHITE", font=("Arial", 9), relief=FLAT) # Menu for choosing font
fonts_MenuButton.pack(side="left", fill="x", expand=False) # Position the menu in which you can choose any font

fonts_MenuButton.menu = Menu(fonts_MenuButton, tearoff = 0) # Create a menu
fonts_MenuButton["menu"] = fonts_MenuButton.menu

# Fonts
fonts_MenuButton.menu.add_command(label=font_name1, font=(font_name1, 13), command=font1) # Font 1 button
fonts_MenuButton.menu.add_command(label=font_name2, font=(font_name2, 13), command=font2) # Font 2 button
fonts_MenuButton.menu.add_command(label=font_name3, font=(font_name3, 13), command=font3) # Font 3 button
fonts_MenuButton.menu.add_command(label=font_name4, font=(font_name4, 13), command=font4) # Font 4 button
fonts_MenuButton.menu.add_command(label=font_name5, font=(font_name5, 13), command=font5) # Font 5 button
fonts_MenuButton.menu.add_command(label=font_name6, font=(font_name6, 13), command=font6) # Font 6 button
fonts_MenuButton.menu.add_command(label=font_name7, font=(font_name7, 13), command=font7) # Font 7 button
# ... 剩余340种字体的添加代码

其中font_name开头的变量用于存储字体名称,fontX函数为菜单按钮的点击回调函数。请问是否有可行的实现方法?


可行实现方法

Tkinter原生的Menu组件并不直接支持滚动条,不过有两种实用的替代方案:

方案1:使用ttk.Combobox替代Menubutton

ttk.Combobox的下拉列表自带滚动功能,适配大量选项场景,代码实现简洁:

import tkinter as tk
from tkinter import ttk

def on_font_selected(event):
    selected_font = font_combobox.get()
    # 替换为你的字体设置逻辑,比如调用对应回调函数
    print(f"选择了字体:{selected_font}")

main_window = tk.Tk()

# 获取系统所有可用字体并排序
available_fonts = list(tk.font.families())
available_fonts.sort()

# 创建带滚动的下拉选择框
font_combobox = ttk.Combobox(main_window, values=available_fonts, state="readonly", font=("Arial",9))
font_combobox.pack(side="left", fill="x", expand=False)
font_combobox.bind("<<ComboboxSelected>>", on_font_selected)

main_window.mainloop()

方案2:自定义带滚动条的弹出菜单

如果需要保留Menubutton的弹出式体验,可以通过Canvas+Frame+Scrollbar组合模拟带滚动的菜单:

import tkinter as tk
from tkinter import FLAT

def show_scrollable_menu(event):
    # 销毁已存在的菜单窗口
    if hasattr(main_window, "scroll_menu_win"):
        main_window.scroll_menu_win.destroy()
    
    # 创建无边框的弹出窗口
    main_window.scroll_menu_win = tk.Toplevel(main_window)
    main_window.scroll_menu_win.overrideredirect(True)
    # 定位到Menubutton下方
    x = main_window.winfo_rootx() + fonts_MenuButton.winfo_x()
    y = main_window.winfo_rooty() + fonts_MenuButton.winfo_y() + fonts_MenuButton.winfo_height()
    main_window.scroll_menu_win.geometry(f"+{x}+{y}")
    
    # 配置滚动条与画布
    scrollbar = tk.Scrollbar(main_window.scroll_menu_win)
    scrollbar.pack(side="right", fill="y")
    
    canvas = tk.Canvas(main_window.scroll_menu_win, yscrollcommand=scrollbar.set)
    canvas.pack(side="left", fill="both", expand=True)
    
    scrollbar.config(command=canvas.yview)
    
    # 创建承载字体按钮的Frame
    font_frame = tk.Frame(canvas)
    canvas.create_window((0,0), window=font_frame, anchor="nw")
    
    # 添加所有字体按钮
    available_fonts = list(tk.font.families())
    available_fonts.sort()
    for font_name in available_fonts:
        btn = tk.Button(font_frame, text=font_name, font=(font_name,13), 
                        command=lambda fn=font_name: select_font(fn))
        btn.pack(fill="x", expand=True)
    
    # 更新画布滚动区域
    font_frame.update_idletasks()
    canvas.config(scrollregion=canvas.bbox("all"))

def select_font(font_name):
    # 替换为你的字体设置逻辑
    print(f"选择了字体:{font_name}")
    # 关闭滚动菜单窗口
    main_window.scroll_menu_win.destroy()

main_window = tk.Tk()

# 原Menubutton
fonts_MenuButton = tk.Menubutton(main_window, text="v", bg="WHITE", fg="BLACK", 
                                 activebackground="WHITE", font=("Arial", 9), relief=FLAT)
fonts_MenuButton.pack(side="left", fill="x", expand=False)
# 绑定点击事件显示自定义滚动菜单
fonts_MenuButton.bind("<Button-1>", show_scrollable_menu)

main_window.mainloop()

方案对比

  • 方案1实现简单,自带系统样式和滚动功能,适合快速开发;
  • 方案2更贴近原生Menubutton的弹出体验,自定义程度更高,但代码量稍大。

内容的提问来源于stack exchange,提问作者Alexander

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 06:27:45