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()
这段代码执行无报错,但菜单并未显示。预期右键点击时能弹出该菜单,请问该如何解决?
解决方法
核心问题与修正步骤:
- 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)
- 避免局部变量被垃圾回收
当前代码中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)
- 可选:注册菜单动作(若需响应点击)
如果需要菜单选项被点击后执行逻辑,需将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
相关产品推荐
相关产品推荐

