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

如何使用XML在PyGtk的菜单中添加带图片的功能按钮

问题原因

  1. <menu>标签属于GMenu模型的XML规范,仅支持<menu>、<section>、<item>三类子节点,直接写<button>属于语法错误,会触发第一个报错。
  2. 绑定了menu_model的Gtk.MenuButton生成的Popover内部已经封装了专门渲染菜单的GtkStack容器,该容器的页面由GTK自动管理,你直接往Stack里添加的控件不会被渲染到可见页面,因此看不到效果。

可行方案

方案1:给GMenu菜单项添加图标(最小改动)

如果只是需要菜单项带图标,不需要额外独立按钮,直接通过GMenu属性配置即可:

  1. 代码初始化部分开启菜单图标显示:
Gtk.Settings.get_default().set_property("gtk-menu-images", True)
  1. 修改MENU_XML,给目标菜单项添加icon属性:
<interface>
    <menu id="app-popover">
        <section>
            <item>
                <attribute name="label">Test action</attribute>
                <attribute name="action">app.sample-action</attribute>
                <attribute name="icon">document-print-symbolic</attribute>
            </item>
        </section>
    </menu>
</interface>

生成的菜单项会自带指定图标,样式和标准按钮一致,原有动作绑定逻辑无需修改。


方案2:自定义Popover容器(支持任意控件组合)

如果需要在菜单外添加独立的带图按钮,手动构建Popover完全自定义内容即可:
修改AppWindow.__init__代码如下:

class AppWindow(Gtk.ApplicationWindow):
    
    def __init__(self, *args, **kwargs):
        Gtk.ApplicationWindow.__init__(self, *args, **kwargs)

        # 读取原有菜单模型
        builder = Gtk.Builder.new_from_string(MENU_XML, -1)
        popover_menu = builder.get_object("app-popover")

        # 手动创建Popover容器
        self.popover = Gtk.Popover()
        popover_box = Gtk.VBox(spacing=6)
        self.popover.add(popover_box)

        # 添加自定义带图按钮
        print_btn = Gtk.Button.new_from_icon_name("document-print-symbolic", Gtk.IconSize.BUTTON)
        print_btn.set_label("打印")
        # 绑定点击动作,也可以关联Gio.Action
        print_btn.connect("clicked", lambda _: print("打印按钮触发"))
        popover_box.pack_start(print_btn, False, False, 0)

        # 添加分隔线和原有菜单项
        popover_box.pack_start(Gtk.Separator(orientation=Gtk.Orientation.HORIZONTAL), False, False, 0)
        original_menu = Gtk.Menu.new_from_model(popover_menu)
        popover_box.pack_start(original_menu, False, False, 0)

        # 绑定到MenuButton
        self.popover_button = Gtk.MenuButton()
        self.popover_button.set_popover(self.popover)

        self.box = Gtk.VBox()
        self.box.pack_start(self.popover_button, False, False, 0)
        self.add(self.box)

        self.maximize()
        self.show_all()

该方式可以自由组合Popover内的所有控件,灵活性最高。


内容的提问来源于stack exchange,提问作者Sylvester is on codidact.com

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 08:39:02