gtk2hs を Glade と組み合わせて使うときのメモ。
Haskell の GUI プログラミングを試したくて、テキストボックスに文字列を入れて Enter を押したらラベルに表示されるような簡単なプログラム echo を、gtk2hs を使って書く実験をしてみた。
で、まず Glade というツールで GUI を定義する XMLを生成して、これを適当に書いた Haskell プログラムに読ませたら、こんなエラーが出た
$ ./echo (echo:4887): libglade-WARNING **: Expected <glade-interface>. Got <interface>. (echo:4887): libglade-WARNING **: did not finish in PARSER_FINISH state echo: user error (Pattern match failure in do expression at echo.hs:8:5-12)
なんか Glade が生成した GUI定義XML の形式に問題があるっぽい。
調べてみると、Glade の出力形式には libglade と GtkBuilder の二通りの方法があり、gtk2hs が対応しているのは前者という事らしいのだが、ファイルを保存するときに libglade を選んでも、事態は全然変わらない。
さらに調べてみると Glade の3.8系 と 3.10系 で大きな違いがあって、出力XML に関してだと 3.10系では libglade 形式が無くなってるらしい。自分は、特に意識しないまま 3.10 を使っていた模様。
この2つのバージョン間で、保存時のダイアログに以下のような違いがある。
XML出力の違いは以下のような感じ<?xml version="1.0" encoding="UTF-8"?> <interface> <requires lib="gtk+" version="2.24"/> <object class="GtkWindow" id="window1"> <property name="can_focus">False</property> <child> …
<?xml version="1.0" encoding="UTF-8"?> <glade-interface> <widget class="GtkWindow" id="window1"> <property name="can_focus">False</property> <child> …
というわけで、Glade の 3.8 系を使えば、gtk2hs がちゃんと処理できる形式の XML になる。
ただし、うちの環境で使ってる Fedora16 なんかでは、「ソフトウェアの追加/削除」から普通に Glade をインストールすると 3.10系が入って来てしまう。従って、この場合 3.8系を別途インストールする必要がある。
これは、ここから glade3-3.8.1.tar.xz を落としてきて、tar Jxf glade3-3.8.1.tar.xz -> ./configure -> make -> make install のようにすれば、/usr/local/bin/glade-3 が使えるようになる。
ちなみに、以下が実験で使った Haskellコード
module Main where import Graphics.UI.Gtk import Graphics.UI.Gtk.Glade import Graphics.UI.Gtk.Gdk.Events as Evt main = do initGUI Just xml <- xmlNew "echo.glade" window <- xmlGetWidget xml castToWindow "window1" onDestroy window mainQuit label <- xmlGetWidget xml castToLabel "label1" entry <- xmlGetWidget xml castToEntry "entry1" onKeyPress window $ \(Evt.Key _ eventSent _ _ _ _ _ _ name _) -> do keyPressHandler label entry name return eventSent widgetShowAll window mainGUI keyPressHandler :: Label -> Entry -> String -> IO () keyPressHandler label entry "Return" = do name <- get entry entryText set label [labelText := name] keyPressHandler _ _ _ = return ()たかだかこれだけのコードを書くのに、かなり骨を折るが、いちおう動作する。
0 件のコメント:
コメントを投稿