Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
411 lines (273 sloc) 13.9 KB
.. _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("class method 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. This argument type list must end with a
comma.
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.PARAM_READABLE` (only read access for external code),
:const:`GObject.PARAM_WRITABLE` (only write access),
:const:`GObject.PARAM_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.PARAM_READABLE) # not writable
bar = GObject.Property(type=str, flags = GObject.PARAM_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.PARAM_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 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 thawed 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 list of the
parameters of the signal, it must end with a comma.
.. 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 recommend 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.PARAM_READABLE
The property is readable.
.. attribute:: GObject.PARAM_WRITABLE
The property is writable.
.. attribute:: GObject.PARAM_READWRITE
The property is readable and writable.
.. _Glade: http://glade.gnome.org/