我正在为lablgtk2编写一系列新的小部件,这是针对Gtk +的OCaml绑定。其中一些小部件可以编辑或呈现相当复杂的信息,因此我对使用模型 - 视图 - 控制器或主题 - 观察者感兴趣,类似于GTree
模块中的内容。
此模块定义了GTree.model
和GTree.view
类,每个类都有可以连接的信号,GTree.model
可以附加到一个或多个GTree.view
'第
在纯OCaml中模仿这个组织并不是那么简单,因为库中可用的代码是C库的绑定。我需要完成以下步骤:
我可以通过1和2,但我不知道如何做3和4.如何做到这一点?
新小部件的定义本身并不成问题。新窗口小部件通常是Gnome画布或复合材料的专用版本。在前一种情况下,我们的新小部件可以作为GObj.widget从Gnome画布继承,在后一种情况下,我们可以使用用于保存合成的容器提供的GObj.widget。这通常看起来像
class view () =
let vbox = GPack.vbox () in
…
object(self)
inherit GObj.widget vbox#as_widget
…
end
绑定为定义新信号的代码提供了大量示例,以便我们可以为我们的小部件定义新信号,如下面的代码片段所示,考虑到没有参数的信号的简单情况:
open GtkSignal
module Event =
struct
let plop : ([>`widget], unit -> unit) t = {
name = "plop_event";
classe = `widget;
marshaller = marshal_unit;
}
let fizz : ([>`widget], unit -> unit) t = {
name = "fizz_event";
classe = `widget;
marshaller = marshal_unit;
}
end
class pill_signals obj =
object (self)
inherit ['a] GObj.gobject_signals (obj :> Gtk.widget Gobject.obj)
method plop = self#connect Event.plop
method fizz = self#connect Event.fizz
end
通过这些定义,我们的view
窗口小部件可以通过定义适当的connect
方法来公开这些信号:
method connect =
new pill_signals obj
似乎函数GtkSignal.emit
用于向对象发出信号,触发已注册的回调。这用作以下签名:
val emit :
'a Gobject.obj ->
sgn:('a, 'b) GtkSignal.t ->
emitter:(cont:('c Gobject.data_set array -> 'd) -> 'b) ->
conv:(Gobject.g_value -> 'd) -> 'b
前两个参数是自我解释的,但不是很清楚,剩下的两个参数是什么。不幸的是,lablgtk源代码中没有使用示例,因为信号是从代码的C端发出的。这两个参数似乎与信号参数的准备有关,具体化为'c Gobject.data_set array
,并且使用标记为~conv
的参数检索产生的值。然而,~cont
- 参数在发射器中的作用仍然需要被清除。
模型定义中棘手的部分是,它应该从GObj.object
继承,以便能够发送接收信号。不幸的是,没有允许直接定义最小Gtk +对象的功能。我走向这个方向最远的是
module Model =
struct
let create () =
GtkObject.make ~classe:"GObject" []
end
let model () =
new model (Model.create ())
调用函数model
来实例化相应的对象会产生消息:
Gtk-CRITICAL **:IA__gtk_object_sink:断言'GTK_IS_OBJECT(对象)'失败
显然,这里有一些可疑的东西,很可能是参数列表(上面代码段中的空列表)太小了。
答案 0 :(得分:0)
LablGTK为Gtk信令机制提供了一个很好的接口,它允许我们使用它而不需要修改GtkSignal
和编组功能。此界面由GUtil
提供,并且整齐记录。
将ML信号添加到LablGTK对象:
{[
class mywidget_signals obj ~mysignal1 ~mysignal2 = object
inherit somewidget_signals obj
inherit add_ml_signals obj [mysignal1#disconnect; mysignal2#disconnect]
method mysignal1 = mysignal1#connect ~after
method mysignal2 = mysignal2#connect ~after
end
class mywidget obj = object (self)
inherit somewidget obj
val mysignal1 = new signal obj
val mysignal2 = new signal obj
method connect = new mywidget_signals obj ~mysignal1 ~mysignal2
method call1 = mysignal1#call
method call2 = mysignal2#call
end
]}
您还可以将ML信号添加到任意对象;只需继承ml_signals
代替widget_signals
和add_ml_signals
。
{[
class mysignals ~mysignal1 ~mysignal2 = object
inherit ml_signals [mysignal1#disconnect; mysignal2#disconnect]
method mysignal1 = mysignal1#connect ~after
method mysignal2 = mysignal2#connect ~after
end
]}
现在很容易解决上面的第1,2,3和4点:
GUtil
定义新信号,而不是GtkSignal
call
的{{1}}方法完成的。['a] GUtil.signal
,实际上没有问题。