如何在GTK2中使用PyGObject将弹出菜单附加到列标题按钮?

6 投票
3 回答
2149 浏览
提问于 2025-04-16 22:58

我想在用户右键点击Gtk.TreeView的表头行时弹出一个上下文菜单。在GTK3中,Gtk.TreeViewColumn有一个叫get_button()的方法,这样做起来很简单;只需要把菜单附加到按钮上,然后连接到一个'clicked'事件就可以了。不过在GTK2中,这个方法就不行了。你只能调用get_widget()方法,如果你没有通过set_widget()设置一个小部件,它会返回None。我尝试把一个包含列名的Gtk.Label放到Gtk.EventBox里,然后把这个作为小部件。连接EventBox到'button_press_event'的回调后,点击它却没有生成事件。

我还尝试做一些类似于这里提到的事情,但在列小部件上调用get_parent()返回的是None,根本无法像他们的代码所暗示的那样到达按钮。

大家找到过什么解决方案吗?

3 个回答

0

我很喜欢在StackOverflow上看到实际的例子,所以我决定也分享一个。所有的功劳都要归给@Johan Dahlin!

#!/usr/bin/env python3

from gi.repository import Gtk

def button_release_event(button, event):
    if event.button == 3:
        menu.popup(None, None, None, None, event.button, event.time)


window = Gtk.Window()
window.connect("destroy", lambda q: Gtk.main_quit())

liststore = Gtk.ListStore(str)
liststore.append(["1"])
liststore.append(["2"])

menu=Gtk.Menu()
menu.append(Gtk.ImageMenuItem("Yep it works!"))
menu.append(Gtk.ImageMenuItem(":)"))
menu.show_all()

treeview = Gtk.TreeView(model=liststore)
window.add(treeview)

treeviewcolumn = Gtk.TreeViewColumn()
treeview.append_column(treeviewcolumn)    

# Set the treeviewcolum as clickable
#
treeviewcolumn.set_clickable(True)

# force Gtk to create a header button for the Gtk.TreeViewColumn
#
label = Gtk.Label("Numbers")
label.show()
treeviewcolumn.set_widget(label)

# fetch the internal GtkButton of the header:
#
widget = treeviewcolumn.get_widget()
while not isinstance(widget, Gtk.Button):
    widget = widget.get_parent()

widget.connect('button-release-event', button_release_event)

cellrenderertext = Gtk.CellRendererText()
treeviewcolumn.pack_start(cellrenderertext, True)
treeviewcolumn.add_attribute(cellrenderertext, 'text', 0)

window.show_all()
Gtk.main()

祝你编程愉快!

0

这看起来确实有点复杂。我查看了一下源代码。显然,parent这个技巧是有效的(它会返回对齐对象),但是你的自定义标签只有在TreeviewColumn被实际创建后才会添加到按钮上,所以在那之前,parent属性的值是None。所以在你调用Treeview的显示命令之后,你应该能够获取到父级(按钮->HBox->对齐->标签),然后就可以把你的处理程序连接到信号上了。

4

其实这很简单,不过你需要用一些小技巧。

首先,你需要强制 Gtk 为 GtkTreeViewColumn 创建一个表头按钮:

    label = gtk.Label("Column title")
    label.show()
    treeview_column.set_widget(label)

接下来,你需要获取表头的内部 GtkButton:

    widget = treeview_column.get_widget()
    while not isinstance(widget, gtk.Button):
        widget = widget.get_parent()

最后,有了按钮的引用,你就可以做一些有用的事情:

    def button_release_event(button, event):
        if event.button == 3:
           menu.popup(event)

    widget.connect('button-release-event', button_release_event)

这些内容来自于 kiwi 库,它有一个 ObjectList,可以提供类似 Python 列表的接口来创建 GtkTreeViews。

撰写回答