开发者

How do you attach a popup menu to a column header button in GTK2 using PyGObject?

开发者 https://www.devze.com 2023-03-26 09:37 出处:网络
I want to popup a context menu when the user right-clicks o开发者_如何学运维n the header row of a Gtk.TreeView. In GTK3, Gtk.TreeViewColumn has a get_button() method, which makes this easy; simply att

I want to popup a context menu when the user right-clicks o开发者_如何学运维n the header row of a Gtk.TreeView. In GTK3, Gtk.TreeViewColumn has a get_button() method, which makes this easy; simply attach the menu to the button and connect it to a 'clicked' event. However, in GTK2, this won't work. You can only call a get_widget() method, which returns None if you haven't set a widget via set_widget(). I've tried putting a Gtk.Label with the column name into a Gtk.EventBox and set that as the widget After connecting the EventBox to a callback for the 'button_press_event', clicking on it doesn't generate the event.

I tried to do something like what's listed here but doing get_parent() on the column widget returns None, and never reaches the button as their code implies.

What solutions have people found for this?


This is pretty easy actually, but you need a couple of hacks.

First you need to force Gtk to create a header button for the GtkTreeViewColumn:

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

After that you need to fetch the internal GtkButton of the header:

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

Finally with a button reference you can do something useful:

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

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

This was taken from the kiwi library which has an ObjectList which provides a python list like api for creating GtkTreeViews.


This indeed seems complicated, I had a look at the source. Apparently the parent trick works (and returns the alignment object), however your custom label is only added to the button after the TreeviewColumn has been realized, so before that the parent attribute stays None So probably latest after your show command of the Treeview, you should be able to retrieve the parents (Button->HBox->Alignment->Label) and can attach your handler to the signal.


I love working examples on S.O, so I decided to post one. All the credits are for @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()

happy hacking!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号