You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Gtk+ Python2.7的TextView右键菜单中添加带子菜单的选项

嘿,我刚好在Python2.7的Gtk2环境下做过类似的需求,给TextView的右键默认菜单加带悬停子菜单的选项其实挺 straightforward的。我给你整理了可运行的代码示例,还有关键步骤的解释:

import gtk

class TextViewContextMenuExample:
    def __init__(self):
        # 创建主窗口
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.set_title("TextView右键菜单示例")
        self.window.connect("destroy", gtk.main_quit)
        self.window.set_size_request(400, 300)

        # 创建滚动容器容纳TextView,支持内容滚动
        scrolled_win = gtk.ScrolledWindow()
        scrolled_win.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.window.add(scrolled_win)

        # 初始化TextView和文本缓冲区
        self.textview = gtk.TextView()
        self.textbuffer = self.textview.get_buffer()
        self.textbuffer.set_text("右键点击我试试!")
        scrolled_win.add(self.textview)

        # 绑定右键菜单触发信号
        self.textview.connect("popup-menu", self.on_popup_menu)

        # 显示所有控件
        self.window.show_all()

    def on_popup_menu(self, textview, event):
        # 获取TextView自带的默认编辑菜单,没有则手动创建
        menu = textview.get_popup_menu()
        if not menu:
            menu = gtk.Menu()

            # 添加默认的复制、粘贴菜单项
            copy_item = gtk.ImageMenuItem(gtk.STOCK_COPY)
            copy_item.connect("activate", self.on_copy)
            menu.append(copy_item)

            paste_item = gtk.ImageMenuItem(gtk.STOCK_PASTE)
            paste_item.connect("activate", self.on_paste)
            menu.append(paste_item)

            # 添加分隔线区分默认项和自定义项
            separator = gtk.SeparatorMenuItem()
            menu.append(separator)

        # 创建自定义主菜单项
        custom_main_item = gtk.MenuItem("我的自定义选项")
        # 创建子菜单容器
        submenu = gtk.Menu()

        # 给子菜单添加选项并绑定点击事件
        sub_item1 = gtk.MenuItem("子选项1 - 替换文本")
        sub_item1.connect("activate", self.on_sub_item1_click)
        submenu.append(sub_item1)

        sub_item2 = gtk.MenuItem("子选项2 - 追加文本")
        sub_item2.connect("activate", self.on_sub_item2_click)
        submenu.append(sub_item2)

        # 子菜单内部分隔线
        sub_sep = gtk.SeparatorMenuItem()
        submenu.append(sub_sep)

        sub_item3 = gtk.MenuItem("子选项3 - 清空文本")
        sub_item3.connect("activate", self.on_sub_item3_click)
        submenu.append(sub_item3)

        # 将子菜单绑定到主菜单项,实现悬停弹出
        custom_main_item.set_submenu(submenu)

        # 在默认菜单末尾添加分隔线和自定义项
        menu.append(gtk.SeparatorMenuItem())
        menu.append(custom_main_item)

        # 显示所有菜单项
        menu.show_all()

        # 在鼠标点击位置弹出菜单
        if event:
            menu.popup(None, None, None, event.button, event.time)
        else:
            menu.popup(None, None, gtk.text_view_popup_menu_position, 0, gtk.get_current_event_time())

        # 返回True表示已处理菜单弹出,避免重复触发默认逻辑
        return True

    # 实现默认编辑功能
    def on_copy(self, widget):
        self.textview.copy_clipboard(gtk.clipboard_get())

    def on_paste(self, widget):
        self.textview.paste_clipboard(gtk.clipboard_get(), None, True)

    # 自定义子菜单点击事件逻辑
    def on_sub_item1_click(self, widget):
        self.textbuffer.set_text("你选择了【子选项1】")

    def on_sub_item2_click(self, widget):
        end_iter = self.textbuffer.get_end_iter()
        self.textbuffer.insert(end_iter, "\n追加的文本来自【子选项2】")

    def on_sub_item3_click(self, widget):
        self.textbuffer.set_text("")

if __name__ == "__main__":
    example = TextViewContextMenuExample()
    gtk.main()

关键细节说明:

  • 信号绑定:通过popup-menu信号拦截右键点击事件,这是修改TextView右键菜单的核心入口。
  • 保留默认功能:先尝试获取TextView自带的编辑菜单,如果没有则手动添加复制、粘贴项,确保原有功能不丢失。
  • 子菜单实现:创建gtk.Menu作为子菜单容器,通过set_submenu()方法关联到主菜单项,鼠标悬停时就会自动弹出子菜单。
  • 菜单弹出位置:调用menu.popup()时传入事件参数,保证菜单精准出现在右键点击的位置。

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

火山引擎 最新活动