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

Python Gtk3:如何让PopoverMenu弹出菜单正常显示?

问题描述

我创建了一个名为Menu的类,代码如下:

class Menu(Gtk.PopoverMenu):
    def __init__(self):
        Gtk.PopoverMenu.__init__(self)
        # Creates a Gio.MenuModel object
        menu = Gio.Menu.new()
        menu.append('Test 1', 'popup.test1')
        menu.append('Test 2', 'popup.test2')
        # Takes Gio.MenuModel as it's first parameter
        self.bind_model(menu, 'contextMenu')

    def show_menu(self):
        self.popup()

在另一个类中通过如下方式实例化该类:

elif event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3:
        popup = Menu()
        popup.show_menu()

这段代码执行无报错,但菜单并未显示。预期右键点击时能弹出该菜单,请问该如何解决?

解决方法

核心问题与修正步骤:

  1. PopoverMenu必须绑定父控件并指定显示位置
    Gtk.PopoverMenu是依附式弹窗,无法独立显示,必须绑定到一个父控件,同时要根据右键点击位置定位弹窗。修改Menu类的初始化和显示方法:
class Menu(Gtk.PopoverMenu):
    def __init__(self, parent_widget):
        super().__init__(parent=parent_widget)  # 绑定父控件
        menu = Gio.Menu.new()
        menu.append('Test 1', 'popup.test1')
        menu.append('Test 2', 'popup.test2')
        self.bind_model(menu, 'contextMenu')

    def show_menu(self, event):
        # 直接使用popup_at_pointer,自动获取鼠标点击位置
        self.popup_at_pointer(event)
  1. 避免局部变量被垃圾回收
    当前代码中popup是事件处理函数内的局部变量,函数执行完毕后会被Python立即回收,导致弹窗还未显示就被销毁。需要将弹窗保存为类的实例变量:
# 在你的主类初始化中添加实例变量
self.context_menu = None

# 事件处理代码修改为:
elif event.type == Gdk.EventType.BUTTON_PRESS and event.button == 3:
    self.context_menu = Menu(parent_widget=self)
    self.context_menu.show_menu(event)
  1. 可选:注册菜单动作(若需响应点击)
    如果需要菜单选项被点击后执行逻辑,需将popup.test1、popup.test2这些动作注册到动作组:
# 在主窗口/控件的初始化方法中添加
action_group = Gio.SimpleActionGroup.new()

# 注册test1动作
test1_action = Gio.SimpleAction.new("test1", None)
test1_action.connect("activate", self.on_test1_clicked)
action_group.add_action(test1_action)

# 注册test2动作
test2_action = Gio.SimpleAction.new("test2", None)
test2_action.connect("activate", self.on_test2_clicked)
action_group.add_action(test2_action)

# 将动作组挂载到控件
self.insert_action_group("popup", action_group)

# 对应的回调函数
def on_test1_clicked(self, action, param):
    print("Test 1 clicked")

def on_test2_clicked(self, action, param):
    print("Test 2 clicked")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 04:41:06