0

Gtk+ の OCaml バインディングである lablgtk2 用の新しいウィジェットのファミリを作成しています。これらのウィジェットの中には、かなり複雑な情報を編集または表示できるものがあります。そのため、GTreeモジュールで見られるものと同様に、model-view-controler または subject-observer の使用に興味があります。

このモジュールはGTree.modelGTree.viewクラスを定義します。それぞれに接続可能なシグナルがあり、GTree.modelは 1 つ以上GTree.viewの に接続できます。

ライブラリで利用可能なコードは C ライブラリのバインディングであるため、純粋な OCaml でこの構成を模倣することはそれほど簡単ではありません。次の手順を実行する必要があります。

  1. 新しいウィジェットの定義
  2. 新しいシグナルの定義
  3. これらの新しいシグナルのトリガー
  4. 新しいモデルの定義

1 と 2 は実行できますが、3 と 4 の実行方法がわかりません。これらを正しく実行するにはどうすればよいですか?

新しいウィジェットの定義

新しいウィジェットの定義自体は問題ありません。新しいウィジェットは、通常、Gnome キャンバスまたはコンポジットの特殊化されたバージョンです。前者の場合、新しいウィジェットは Gnome キャンバスから GObj.widget として継承でき、後者の場合、コンポジットを保持するために使用されるコンテナーによって提供される 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

最初の 2 つのパラメーターは一目瞭然ですが、残りの 2 つのパラメーターが何であるかは明確ではありません。残念ながら、信号はコードの C 側から放出されるため、lablgtk ソース コードには使用例がありません。これらの 2 つの引数は、 として実体化されたシグナルの引数の準備と'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 (オブジェクト)' が失敗しました

明らかに、ここには怪しいものがあります。おそらく、パラメーター リスト (上記のスニペットの空のリスト) が小さすぎたのでしょう。

4

1 に答える 1

0

LablGTK は、Gtk シグナル伝達メカニズムへの優れたインターフェイスを提供します。これにより、GtkSignal関数をいじったりマーシャリングしたりすることなく、LablGTK を使用できます。このインターフェースはによって提供されGUtil、きちんと文書化されています。


モジュールのドキュメントに記載されている 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 シグナルを任意のオブジェクトに追加することもできます。andml_signalsの代わりにfrom を継承するだけです。widget_signalsadd_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 に対処するのは簡単です。

  1. これでいい
  2. GUtilの代わりに新しいシグナルを定義するために使用します。GtkSignal
  3. 新しい信号のトリガーは、 のcall方法で実行され['a] GUtil.signalます。
  4. もう使っていないのでGtkSignal、実際には問題ありません。
于 2015-01-29T09:52:42.437 に答える