对象系统¶
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¶ 属性可读可写。