Search code examples
pythongtkpygobject

How do I get parameter value from a GParam object


What: Gtk+ 3 with PyGObject bindings and Python 2.7.

Question: How can I get the value of a GParamObject? I assume it has a value, (otherwise what would be the point of it?) but I have spent several hours googling and experimenting and have not been able find the answer to this seemingly simple question. Maybe my assumption that is has a value is unfounded.

Background: I have a Gtk.Stack, and I have connected a callback to the "notify::visible-child" signals that does some stuff when the visible-child changes. Something like this

stack.connect("notify::visible-child", on_stack_changed)

def on_stack_changed(stack, param):
    print "stack's visible child changed"
    print param  # Prints: <GParamObject 'visible-child'>

Now, since the GTK.Stack docs indicate that the visible_child property's value is the visible child widget, I expect to be able to get a reference to the widget from the param passed to my callback. But I have not been able to figure out how to get any value from the GParam object.

I have tried every variation of things like param.value, param.get_value() etc. that I could think of, but to no avail.

Of course, since the stack object is also passed to my callback, I could always do stack. get_visible_child(), but that is no fun, is it? :D

So, any explanation of the GParamObject, its intended use, or links to examples of its use would be greatly appreciated.

Edit: Here is a standalone example.

#!/usr/bin/env python

import os, gi

gi.require_version('Gtk', '3.0')
gi.require_version('Gdk', '3.0')

from gi.repository import Gtk, Gdk

def on_stack_changed(stack, param):
    for attr in dir(param):
        print "{}: {}".format(attr, getattr(param, attr))

stack = Gtk.Stack()
stack.add_titled(Gtk.Label('Child 1'), 'child1', 'Child 1')
stack.add_titled(Gtk.Label('Child 2'), 'child2', 'Child 2')
stack.connect("notify::visible-child", on_stack_changed)

stack_switcher = Gtk.StackSwitcher(stack=stack)

header_bar = Gtk.HeaderBar(custom_title=stack_switcher, show_close_button=True)

window = Gtk.Window()
window.set_default_size(500, 250)
window.set_titlebar(header_bar)
window.add(stack)

window.connect('destroy', Gtk.main_quit)

window.show_all()

Gtk.main()

As suggested by liberforce, I tried print dir(param) which results in this output:

__doc__: The widget currently visible in the stack
__gtype__: <GType GParamObject (94151103218704)>
blurb: The widget currently visible in the stack
flags: 1073742051
name: visible-child
nick: Visible child
owner_type: <GType GtkStack (94151105445744)>
value_type: <GType GtkWidget (94151104851072)>

This helps a great deal in understanding what information is available from the GParamObject. As expected the value_type is a GtkWidget, but I still don't see how to get the value itself.


Solution

  • I think it's because it doesn't exist there. What you get in param seems to be a GParamSpec which is just metadata about a parameter, holding its name, type, flags... I can't find a reference on GParamObject in the PyGObject documentation. But If I look the C documentation of the notify signal, indeed, thats a GParamSpec that is passed there, so that may be a GObject.ParamSpecObject

    So I think your get_visible_child is the way to go. You may get the same result in a more flexible way using using the GParamSpec with stack.get_property(param.name).

    UPDATE:

    Here's the standalone example modified: In the callback, I use 3 different ways of getting the visible child, all working. They all return the same object instance, as confirmed by id.

    #!/usr/bin/env python
    
    import os, gi
    
    gi.require_version('Gtk', '3.0')
    gi.require_version('Gdk', '3.0')
    
    from gi.repository import Gtk, Gdk
    
    def on_stack_changed(stack, param):
        print 'stack.get_visible_child():      {}'.format(id(stack.get_visible_child()))
        print 'stack.get_property(param.name): {}'.format(id(stack.get_property(param.name)))
        print 'stack.props.visible_child:      {}'.format(id(stack.props.visible_child))
    
    stack = Gtk.Stack()
    stack.add_titled(Gtk.Label('Child 1'), 'child1', 'Child 1')
    stack.add_titled(Gtk.Label('Child 2'), 'child2', 'Child 2')
    stack.connect("notify::visible-child", on_stack_changed)
    
    stack_switcher = Gtk.StackSwitcher(stack=stack)
    
    header_bar = Gtk.HeaderBar(custom_title=stack_switcher, show_close_button=True)
    
    window = Gtk.Window()
    window.set_default_size(500, 250)
    window.set_titlebar(header_bar)
    window.add(stack)
    
    window.connect('destroy', Gtk.main_quit)
    
    window.show_all()
    
    Gtk.main()
    

    Using print vars(param) may help you see what is really in your object.