F#はじめました

明日はF#読書会だそうです。
そして、ちょっと勉強がてらこちらのを写経してみました。
#98 FunctionalでReactiveなGUIを作る
普通に写経するのも単調なのでGUIにはGTK#を使って見ます
使ったことないけど上手に使えますかね

ReactiveForm.fs

module ReactiveForm

open Gtk
open Gdk

type ReactiveWindow () as self = 
 inherit Gtk.Window("Form1")
 let numLabel = 
  new Gtk.Label ( "0", 
   Allocation = new Gdk.Rectangle (261, 9, 11, 12),
   TooltipText = "Num"
   )
 let incButton = 
  new Gtk.Button ("値を増やす", 
   Allocation = new Gdk.Rectangle(197, 24, 75, 23),
   TooltipText = "B1"
   )
 do
  let controlBox = 
   new Gtk.VBox(
    Allocation = new Gdk.Rectangle(0, 0, 100, 100)
   )
  //↓なんかここが冗長で気に入らない Add [ A; B] みたいにできないの
  //  というかctorで書かせて
  controlBox.Add numLabel
  controlBox.Add incButton
  self.DefaultSize <- new Gdk.Size(200, 200)
  self.Add controlBox
 let increment_click = 
  incButton.Clicked
  |> Observable.scan(fun n e -> n + 1) 0
 let mutable counter = 0
 do
  increment_click
   |> Observable.subscribe(fun ob -> numLabel.Text <- ob.ToString()) 
   |> ignore

Program.fs

module Program

open ReactiveForm
open Gtk

[<EntryPoint>]
let main _ = 
 Gtk.Application.Init();
 let mainWindow = new ReactiveWindow();
 mainWindow.ShowAll();
 Gtk.Application.Run();
 0

まあサイズとか全然違うじゃねーかって突っ込みはなしでお願いします

Gtk#の使い方
  1. GTK#をインストールする
  2. インストールしたフォルダのLibあたりにあるdllを全部参照
  3. 開始時にはGtk.Application.InitをしてRunで実行
コツというか、気づいたこと
  • Gtk.Boxをくみあわせてレイアウト
  • Gtk.WindowはGtk.BinなのでまとめたBoxをくっつける
  • Gtk.Container.Childrenはread-onlyなので追加はベタ書き
  • というかGtk.ContainerがWidgetのリストで初期化できないのはどうなの?

あとこれUbuntuのMonoで動くかなと思ってたらコンパイルがまったく進みませんでした。不思議<調べろ

(2011/09/08追記)Addキモいよねの解決策

こういうのがあれば、Addを一個ずつしなくてよくなりますよねと

let rec GtkAddMany (container:Gtk.Container) (widgets:Gtk.Widget list )= 
 match widgets with
  | x::xs -> (container.Add x; GtkAddMany container xs )
  | [] -> ignore;
  GtkAddMany controlBox  [ numLabel; incButton] |> ignore

名前はこちらからいただきました

さらに追記

ご指摘いただきました

let GtkAddMany (container : Gtk.Container) (widgets : Gtk.Widget list) =
    List.iter (fun widget -> container.Add widget) widgets

List.Iter

これAddあるコンテナに対してDuck typingできるんじゃない?

inlineを使えばもうちょっと抽象化できるんだけどリンク先の通りご利用は控えめにという感じですね