python gtk

Last edited

GObject Basics

Initialization

Properties describe the configuration and state of a gobject.

3 ways to get/set them:

label = Gtk.Label(label='Hello World')

label = Gtk.Label()
label.set_label('Hello World')

# If you made a custom subclass of GObject.Object
# and don't have getters/setter functions
label = Gtk.Label()
label.set_property('label', 'Hello World')

See which properties are available for a gobject:

widget = Gtk.Box()
print(dir(widget.props))

Bindings

You can bind two compatible properties together.

Example: I move a slider another GObject will change it’s text to the position. We have bound what happens to one object affects another.

entry = Gtk.Entry()
label = Gtk.Label()
entry.bind_property('text', label, 'label', GObject.BindingFlags.DEFAULT)

Bindings with Transformations

Sometimes you want to bind two properties that are incompatible or simple need to apply trasnformation between the values (e.g, slider * 2 = text)

To do this pass in a custom transformation function.

def transform_to(_binding, value):
   return bool(value)  # Return int converted to a bool

def transform_from(_binding, value):
    return int(value)  # Return bool converted to a int

source.bind_property(
    'int_prop',
    target,
    'bool_prop',
    GObject.BindingFlags.BIDIRECTIONAL,
    transform_to,
    transform_from
)

Signals

GObject signals are a system for registering callbacks for specific events.

the handler_id is a ticket that identifies the connect() registration, like a PID

signal

Example with no data

def on_event(gobject, data):
    ...

my_object.connect('event', on_event, data)
gobject.disconnect(handler_id) 

this handler is ‘unregistered’, if the signal hits again it won’t trigger this callback.

When would you need to disable a handler?

  • one shot handlers
  • temporarily muting (disable callback till X)
  • if you destoyed the thing it’s actioning

Notify signal

When any of a GObject’s properties change it will emit a notify signal, so you can listen to these as events.

def callback(label, _pspec):
    print(f'The label prop changed to {label.props.label}')

label = Gtk.Label()
label.connect('notify::label', callback)

Inhertiance

Typicall you inhert Gtk.Widget, which inturn inherts the top level GObject.Object.

He’res a full example, with a class signal. In the use the class is registering it’s own signal which the class inturn calls.

from gi.repository import GObject

class AnotherObject(GObject.Object):
    value = 0

    @GObject.Property(type=int, minimum=0, maximum=100)
    def prop_int(self):
        return self.value

    @prop_int.setter
    def prop_int(self, value):
        old = self.value
        self.value = value
        self.emit('value_changed', old, value)      # fire the signal

    # Defining the signal: its name comes from the method name, and it carries two ints (old, new)
    @GObject.Signal(flags=GObject.SignalFlags.RUN_LAST, arg_types=(int, int))
    def value_changed(self, old, new):
        """Class's own handler, runs on every emission"""
        print(f'[class handler] {old} -> {new}')


my_object = AnotherObject()

def on_value_changed(obj, old, new):
    print(f'[connected handler] {old} -> {new}')

hid = my_object.connect('value_changed', on_value_changed)

my_object.prop_int = 52

# Results:
# [connected handler] 0 -> 52
# [class handler]     0 -> 52