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

Python 如何使用PyGObject将弹出菜单附加到GTK2中的列标题按钮?,python,gtk,pygtk,pygobject,Python,Gtk,Pygtk,Pygobject,我想在用户右键单击Gtk.TreeView的标题行时弹出一个上下文菜单。在GTK3中,Gtk.TreeViewColumn有一个get_button()方法,这使得这很容易;只需将菜单附加到按钮,并将其连接到“单击”事件。然而,在GTK2中,这将不起作用。您只能调用get\u widget()方法,如果未通过set\u widget()设置小部件,该方法将不返回任何值。我已经尝试将一个列名称为的Gtk.Label放入Gtk.EventBox中,并在将EventBox连接到“按钮按下事件”的回调后

我想在用户右键单击
Gtk.TreeView
的标题行时弹出一个上下文菜单。在GTK3中,
Gtk.TreeViewColumn
有一个get_button()方法,这使得这很容易;只需将菜单附加到按钮,并将其连接到“单击”事件。然而,在GTK2中,这将不起作用。您只能调用
get\u widget()
方法,如果未通过
set\u widget()
设置小部件,该方法将不返回任何值。我已经尝试将一个列名称为的
Gtk.Label
放入
Gtk.EventBox
中,并在将
EventBox
连接到“按钮按下事件”的回调后将其设置为小部件,单击它不会生成事件

我试着做一些类似于列出的事情,但在column小部件上执行
get\u parent()
时不会返回None,也不会像代码所暗示的那样到达按钮


人们找到了什么解决方案?

这看起来确实很复杂,我看了一下。显然,
parent
技巧有效(并返回对齐对象),但是自定义标签仅在实现Treeview列后添加到按钮,因此在此之前,
parent
属性保持
None
,因此可能最迟在Treeview的show命令之后,您应该能够检索父项(按钮->HBox->对齐->标签),并可以将处理程序附加到信号。

这实际上非常简单,但您需要一些技巧

首先,需要强制Gtk为GtkTreeViewColumn创建标题按钮:

    label = gtk.Label("Column title")
    label.show()
    treeview_column.set_widget(label)
之后,您需要获取标头的内部GTK按钮:

    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)

这是从库中获取的,它提供了一个类似python的api列表,用于创建GTKTreeView。

我喜欢在S.O上工作的示例,所以我决定发布一个。所有的学分都是为了@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()

快乐的黑客

我应该通过“在GTK2中,这不起作用”来澄清这一点,我应该说,“在GTK2中,
get_button()
方法没有实现。现在我还发现,
菜单。附加_到_小部件()
菜单。popup()
显然在GTK2中是不可内省的。根据,在GTK3
菜单中。popup()
是通过重写实现的,但是我找不到关于如何实现的文档。我用Perl编写,但同样的方法也可以。谢谢!注意,在调用get_小部件之前,我必须将该列添加到树视图中。