.. _objects: Objects ======= GObject is the fundamental type providing the common attributes and methods for all object types in GTK+, Pango and other libraries based on GObject. The :class:`GObject.GObject` class provides methods for object construction and destruction, property access methods, and signal support. This section will introduce some important aspects about the GObject implementation in Python. Inherit from GObject.GObject ---------------------------- A native GObject is accessible via :class:`GObject.GObject`. It is rarely instantiated directly, we generally use inherited class. A :class:`Gtk.Widget` is an inherited class of a :class:`GObject.GObject`. It may be interesting to make an inherited class to create a new widget, like a settings dialog. To inherit from :class:`GObject.GObject`, you must call :meth:`GObject.GObject.__init__` in your constructor (if the class inherits from :class:`Gtk.Button`, it must call :func:`Gtk.Button.__init__` for instance), like in the example below: .. code-block:: python from gi.repository import GObject class MyObject(GObject.GObject): def __init__(self): GObject.GObject.__init__(self) Signals ------- Signals connect arbitrary application-specific events with any number of listeners. For example, in GTK+, every user event (keystroke or mouse move) is received from the X server and generates a GTK+ event under the form of a signal emission on a given object instance. Each signal is registered in the type system together with the type on which it can be emitted: users of the type are said to connect to the signal on a given type instance when they register a function to be invoked upon the signal emission. Users can also emit the signal by themselves or stop the emission of the signal from within one of the functions connected to the signal. Receive signals ^^^^^^^^^^^^^^^ See :ref:`signals` Create new signals ^^^^^^^^^^^^^^^^^^ New signals can be created by adding them to :attr:`GObject.GObject.__gsignals__`, a dictionary: When a new signal is created, a method handler can also be defined, it will be called each time the signal is emitted. It is called do_signal_name. .. code-block:: python class MyObject(GObject.GObject): __gsignals__ = { 'my_signal': (GObject.SIGNAL_RUN_FIRST, None, (int,)) } def do_my_signal(self, arg): print("method handler for `my_signal' called with argument", arg) :const:`GObject.SIGNAL_RUN_FIRST` indicates that this signal will invoke the object method handler (:meth:`do_my_signal` here) in the first emission stage. Alternatives are :const:`GObject.SIGNAL_RUN_LAST` (the method handler will be invoked in the third emission stage) and :const:`GObject.SIGNAL_RUN_CLEANUP` (invoke the method handler in the last emission stage). The second part, ``None``, indicates the return type of the signal, usually ``None``. ``(int,)`` indicates the signal arguments, here, the signal will only take one argument, whose type is int. Types of arguments required by signal are declared as a sequence, here it is a one-element tuple. Signals can be emitted using :meth:`GObject.GObject.emit`: .. code-block:: python my_obj.emit("my_signal", 42) # emit the signal "my_signal", with the # argument 42 Properties ---------- One of GObject's nice features is its generic get/set mechanism for object properties. Each class inherited from :class:`GObject.GObject` can define new properties. Each property has a type which never changes (e.g. str, float, int...). For instance, they are used for :class:`Gtk.Button` where there is a "label" property which contains the text of the button. Use existing properties ^^^^^^^^^^^^^^^^^^^^^^^ The class :class:`GObject.GObject` provides several useful functions to manage existing properties, :func:`GObject.GObject.get_property` and :func:`GObject.GObject.set_property`. Some properties also have functions dedicated to them, called getter and setter. For the property "label" of a button, there are two functions to get and set them, :func:`Gtk.Button.get_label` and :func:`Gtk.Button.set_label`. Create new properties ^^^^^^^^^^^^^^^^^^^^^ A property is defined with a name and a type. Even if Python itself is dynamically typed, you can't change the type of a property once it is defined. A property can be created using :class:`GObject.Property`. .. code-block:: python from gi.repository import GObject class MyObject(GObject.GObject): foo = GObject.Property(type=str, default='bar') property_float = GObject.Property(type=float) def __init__(self): GObject.GObject.__init__(self) Properties can also be read-only, if you want some properties to be readable but not writable. To do so, you can add some flags to the property definition, to control read/write access. Flags are :const:`GObject.ParamFlags.READABLE` (only read access for external code), :const:`GObject.ParamFlags.WRITABLE` (only write access), :const:`GObject.ParamFlags.READWRITE` (public): .. there is also construct things, but they .. doesn't seem to be functional in Python .. code-block:: python foo = GObject.Property(type=str, flags = GObject.ParamFlags.READABLE) # not writable bar = GObject.Property(type=str, flags = GObject.ParamFlags.WRITABLE) # not readable You can also define new read-only properties with a new method decorated with :class:`GObject.Property`: .. code-block:: python from gi.repository import GObject class MyObject(GObject.GObject): def __init__(self): GObject.GObject.__init__(self) @GObject.Property def readonly(self): return 'This is read-only.' You can get this property using: .. code-block:: python my_object = MyObject() print(my_object.readonly) print(my_object.get_property("readonly")) The API of :class:`GObject.Property` is similar to the builtin :py:func:`property`. You can create property setter in a way similar to Python property: .. code-block:: python class AnotherObject(GObject.Object): value = 0 @GObject.Property def prop(self): 'Read only property.' return 1 @GObject.Property(type=int) def propInt(self): 'Read-write integer property.' return self.value @propInt.setter def propInt(self, value): self.value = value There is also a way to define minimum and maximum values for numbers, using a more verbose form: .. code-block:: python from gi.repository import GObject class MyObject(GObject.GObject): __gproperties__ = { "int-prop": (int, # type "integer prop", # nick "A property that contains an integer", # blurb 1, # min 5, # max 2, # default GObject.ParamFlags.READWRITE # flags ), } def __init__(self): GObject.GObject.__init__(self) self.int_prop = 2 def do_get_property(self, prop): if prop.name == 'int-prop': return self.int_prop else: raise AttributeError('unknown property %s' % prop.name) def do_set_property(self, prop, value): if prop.name == 'int-prop': self.int_prop = value else: raise AttributeError('unknown property %s' % prop.name) Properties must be defined in :attr:`GObject.GObject.__gproperties__`, a dictionary, and handled in do_get_property and do_set_property. Watch properties ^^^^^^^^^^^^^^^^ When a property is modified, a signal is emitted, whose name is "notify::property-name": .. code-block:: python my_object = MyObject() def on_notify_foo(obj, gparamstring): print("foo changed") my_object.connect("notify::foo", on_notify_foo) my_object.set_property("foo", "bar") # on_notify_foo will be called Note that you have to use the canonical property name when connecting to the notify signals, as explained in :func:`GObject.Object.signals.notify`. For instance, for a Python property `foo_bar_baz` you would connect to the signal `notify::foo-bar-baz` using .. code-block:: python my_object = MyObject() def on_notify_foo_bar_baz(obj, gparamstring): print("foo_bar_baz changed") my_object.connect("notify::foo-bar-baz", on_notify_foo_bar_baz) API --- .. class:: GObject.GObject .. method:: get_property(property_name) Retrieves a property value. .. method:: set_property(property_name, value) Set property *property_name* to *value*. .. method:: emit(signal_name, ...) Emit signal *signal_name*. Signal arguments must follow, e.g. if your signal is of type ``(int,)``, it must be emitted with:: self.emit(signal_name, 42) .. method:: freeze_notify() This method freezes all the "notify::" signals (which are emitted when any property is changed) until the :meth:`thaw_notify` method is called. It is recommended to use the *with* statement when calling :meth:`freeze_notify`, that way it is ensured that :meth:`thaw_notify` is called implicitly at the end of the block:: with an_object.freeze_notify(): # Do your work here ... .. method:: thaw_notify() Thaw all the "notify::" signals which were frozen by :meth:`freeze_notify`. It is recommended to not call :meth:`thaw_notify` explicitly but use :meth:`freeze_notify` together with the *with* statement. .. method:: handler_block(handler_id) Blocks a handler of an instance so it will not be called during any signal emissions unless :meth:`handler_unblock` is called for that *handler_id*. Thus "blocking" a signal handler means to temporarily deactivate it, a signal handler has to be unblocked exactly the same amount of times it has been blocked before to become active again. It is recommended to use :meth:`handler_block` in conjunction with the *with* statement which will call :meth:`handler_unblock` implicitly at the end of the block:: with an_object.handler_block(handler_id): # Do your work here ... .. method:: handler_unblock(handler_id) Undoes the effect of :meth:`handler_block`. A blocked handler is skipped during signal emissions and will not be invoked until it has been unblocked exactly the amount of times it has been blocked before. It is recommended to not call :meth:`handler_unblock` explicitly but use :meth:`handler_block` together with the *with* statement. .. attribute:: __gsignals__ A dictionary where inherited class can define new signals. Each element in the dictionary is a new signal. The key is the signal name. The value is a tuple, with the form:: (GObject.SIGNAL_RUN_FIRST, None, (int,)) :const:`GObject.SIGNAL_RUN_FIRST` can be replaced with :const:`GObject.SIGNAL_RUN_LAST` or :const:`GObject.SIGNAL_RUN_CLEANUP`. ``None`` is the return type of the signal. ``(int,)`` is the tuple of the parameters of the signal. .. attribute:: __gproperties__ .. based on http://www.pygtk.org/articles/subclassing-gobject/sub-classing-gobject-in-python.htm The :attr:`__gproperties__` dictionary is a class property where you define the properties of your object. This is not the recommended way to define new properties, the method written above is much less verbose. The benefits of this method is that a property can be defined with more settings, like the minimum or the maximum for numbers. The key is the name of the property The value is a tuple which describe the property. The number of elements of this tuple depends on its first element but the tuple will always contain at least the following items: The first element is the property's type (e.g. ``int``, ``float``...). The second element is the property's nick name, which is a string with a short description of the property. This is generally used by programs with strong introspection capabilities, like the graphical user interface builder `Glade`_. The third one is the property's description or blurb, which is another string with a longer description of the property. Also used by `Glade`_ and similar programs. The last one (which is not necessarily the forth one as we will see later) is the property's flags: :const:`GObject.PARAM_READABLE`, :const:`GObject.PARAM_WRITABLE`, :const:`GObject.PARAM_READWRITE`. The absolute length of the tuple depends on the property type (the first element of the tuple). Thus we have the following situations: If the type is ``bool`` or ``str``, the forth element is the default value of the property. If the type is ``int`` or ``float``, the forth element is the minimum accepted value, the fifth element is the maximum accepted value and the sixth element is the default value. If the type is not one of these, there is no extra element. .. attribute:: GObject.SIGNAL_RUN_FIRST Invoke the object method handler in the first emission stage. .. attribute:: GObject.SIGNAL_RUN_LAST Invoke the object method handler in the third emission stage. .. attribute:: GObject.SIGNAL_RUN_CLEANUP Invoke the object method handler in the last emission stage. .. attribute:: GObject.ParamFlags.READABLE The property is readable. .. attribute:: GObject.ParamFlags.WRITABLE The property is writable. .. attribute:: GObject.ParamFlags.READWRITE The property is readable and writable. .. _Glade: https://glade.gnome.org/