对象系统¶
GObject 是基础类型提供了Gtk+对象系统需要的所有属性和方法。 GObject.GObject
提供了构造和析构对象的方法,属性访问方法和信号支持。
本节将要介绍Python实现的GObject一些重要的方面。
从GObject.GObject继承¶
一个原生的GObject可以通过 GObject.GObject
访问,但通常很少直接实例化,而是
使用继承后的类。 Gtk.Widget
就是一个继承自 GObject.GObject
的类。
创建一个继承类来创建一个新的如设置对话框的新控件通常很有趣。
要从 GObject.GObject
继承,你必须在你的构造函数中调用
GObject.GObject.__init__()
,例如如果你的类继承自 Gtk.Button
,则必须
调用 Gtk.Button.__init__()
, 就像下面这样。
from gi.repository import GObject
class MyObject(GObject.GObject):
def __init__(self):
GObject.GObject.__init__(self)
信号¶
信号可以随意的连接到程序相关的事件,可以有任意多个收听者。例如, 在GTK+里面,每一个 用户事件(按键或鼠标移动) 从X server接收后产生一个GTK+事件在给的的对象实例上触发信号。
每一个信号都与其可以触发的类型一起在类型系统里面注册:当类型的使用者注册信号触发 时的回调函数时,要链接信号到给定类型的实例。
创建新的信号¶
可以通过添加信号到 GObject.GObject.__gsignals__
字典中创建新的信号。
当创建新的信号时也可以定义一个处理方法,该方法会在每次信号触发时调用,叫做 do_signal_name 。
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
GObject.SIGNAL_RUN_FIRST
指示在信号触发的第一阶段调用对象方法
(此处:meth:do_my_signal)。也可以设置为 GObject.SIGNAL_RUN_LAST
(
方法在信号触发的第三阶段调用)和 GObject.SIGNAL_RUN_CLEANUP
(在信号触发
的最后一个阶段调用)。
第二个参数, None
指示信号的返回类型,通常为 None
。
(int,)
指示信号的参数,此处信号只接收一个参数,类型为 int 。参数类型列表必须
以逗号结束。
信号可以使用 GObject.GObject.emit()
触发。
my_obj.emit("my_signal", 42) # emit the signal "my_signal", with the
# argument 42
属性¶
GObject一个很好的特性就是其对于对象属性的get/set方法。每一个继承自 GObject.GObject
的类都可以定义新的属性,每一个属性作为一个类型永远不会改变(例如 str, float, int等)。
例如 Gtk.Button
的 “label” 属性包含了按钮的文本。
使用已有的属性¶
GObject.GObject
提供了多个很有用的函数来管理已有的属性,
GObject.GObject.get_property()
和 GObject.GObject.set_property()
。
一些属性也有他们相应的函数,叫做getter和setter。对于按钮的 “label” 属性,有两个函数
来获取和设置该属性, Gtk.Button.get_label()
和 Gtk.Button.set_label()
。
创建新的属性¶
属性通过名字和类型定义,即使python是动态类型的,一旦定义你也不能改变属性的类型。
属性可以通过 GObject.property()
创建。
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)
如果你想让某些属性只读不可写,属性也可以为只读的。要这样做,你可以给属性定义添加
一些标志flags,来控制读写权限。标志有 GObject.PARAM_READABLE
(只能通过
外部代码读取), GObject.PARAM_WRITABLE
(只可写),
GObject.PARAM_READWRITE
(public):
foo = GObject.property(type=str, flags = GObject.PARAM_READABLE) # won't be writable
bar = GObject.property(type=str, flags = GObject.PARAM_WRITABLE) # won't be readable
你也可以通过 GObject.property()
与函数修饰符创建新的函数来定义只读属性。
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.'
你可以使用以下代码获取该属性:
my_object = MyObject()
print my_object.readonly
print my_object.get_property("readonly")
也有定义数值类型属性的最大值和最小值的方法,需要使用更加复杂的形式:
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
属性必须通过 GObject.GObject.__gproperties__
字典定义,并通过
do_get_property 和 do_set_property 来处理。
监视属性¶
当属性被修改时,会触发一个信号, “notify::property_name” :
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
API¶
-
class
GObject.
GObject
¶ -
get_property
(property_name)¶ 获取属性的值。
-
set_property
(property_name, value)¶ 设置属性 property_name 的值为 value 。
-
emit
(signal_name, ...)¶ 触发信号 signal_name 。信号的参数必须在后面传递,例如,如果你的信号类型 为
(int,)
,则要像下面这样触发:self.emit(signal_name, 42)
-
freeze_notify
()¶ 本函数会冻结所有 “notify::” 信号(这些信号会在属性改变时触发) 指导
thaw_notify()
被调用。建议调用
freeze_notify()
时使用 with 语句,这样可以确保thaw_notify()
在语句块的最后被调用:with an_object.freeze_notify(): # Do your work here ...
-
thaw_notify
()¶ 解冻所有的被
freeze_notify()
冻结的 “notify::” 信号。建议不要明确地调用
thaw_notify()
而是 with 语句与freeze_notify()
一起使用。
-
handler_block
(handler_id)¶ 阻塞实例的处理函数 handler_id 因此在任何信号触发之时都不会被调用,直到
handler_unblock()
被调用。因此 “阻塞” 一个信号处理函数意味着临时 关闭它,信号处理函数必须与之前阻塞次数相同的取消阻塞才能被再次激活。建议
handler_block()
与 with 语句一起使用,这样会在语句块的最后 隐式调用handler_unblock()
with an_object.handler_block(handler_id): # Do your work here ...
-
handler_unblock
(handler_id)¶ 取消
handler_block()
的效果。阻塞后的处理函数会在信号被触发时略过, 并且直到取消阻塞相同次数之前不会被调用。建议不要直接调用
handler_unblock()
而是与 with 语句一起使用handler_block()
。
-
__gsignals__
¶ 一个继承类可以定义新信号的字典。
字典中的每一个元素都是一个新的信号。key为信号的名字,值为一个元组,如下:
(GObject.SIGNAL_RUN_FIRST, None, (int,))
GObject.SIGNAL_RUN_FIRST
可以被替换为GObject.SIGNAL_RUN_LAST
或者GObject.SIGNAL_RUN_CLEANUP
。None
为信号的返回类型。(int,)
为参数的列表,必须以逗号结尾。
-
__gproperties__
¶ __gproperties__
字典是一个可以定义你的对象属性的属性。这并不是建议 的方式定义新属性,上面提到的方法更加的简洁。本方法的优点是可以对属性作更多 的设置,像数值类型的最大值与最小值之类。key 为属性的名字。
value 为描述属性的元组。 元组中元素的数目依赖于第一个元素,但一般至少都会包含下面的元素。
第一个元素为属性的类型(例如
int
,float
等)。第二个元素是属性的小名(昵称),即对属性简短描述的字符串。这通常用于有 很强内省能力的程序,像GUI builder Glade 。
第三个是属性的描述或导语,即另一个更长的,描述属性的字符串。也是给 Glade 及类似程序使用的。
最后一个为属性的标志flags: :
GObject.PARAM_READABLE
, ::const::GObject.PARAM_WRITABLE,GObject.PARAM_READWRITE
。 稍后我们会看到,这并不见得是第四个参数。元组的长度依赖于属性的类型(元组的地一个元素)。具体包括下面的情形:
如果类型为
bool
或者str
,第四个元素为属性的默认值。如果类型为
int
或者float
,第四个元素是可接收的最小值,第五个 为可接收的最大值,第六个为其默认值。如果类型不是上面这些,则没有额外的元素。
-
-
GObject.
SIGNAL_RUN_FIRST
¶ 在信号触发第一阶段调用处理方法。
-
GObject.
SIGNAL_RUN_LAST
¶ 在信号触发第三阶段调用处理方法。
-
GObject.
SIGNAL_RUN_CLEANUP
¶ 在信号触发最后一个阶段调用处理方法。
-
GObject.
PARAM_READABLE
¶ 属性只读。
-
GObject.
PARAM_WRITABLE
¶ 属性只写。
-
GObject.
PARAM_READWRITE
¶ 属性可读可写。