Wednesday, November 11, 2009

“Hello GTK#” from the latest IronPython and F#

A little post to record a short bit of spiking with GTK# as UI toolkit, porting the simple C# examples from here to my preferred .net languages. Neither of these explorations are totally novel -- there are examples in either language to Google, but not all of them recorded all the details of the slight rough spots that needed a little working (and they were often not at all recent, either).

For IronPython 2.6 latest with GTK# 2.12.9-2, running the programs as ipy Program.py, the code looks like

import clr
clr.AddReference('gtk-sharp')
from System import *
from Gtk import *
def OnDelete(sender, args):
Application.Quit()
args.RetVal = True
click_count = 0
def OnButtonClick(sender, args):
global click_count
click_count += 1
Console.WriteLine("Button Click {0}", click_count)
def RealEntryPoint():
## Create the window
Application.Init();
wnd = Window("IronPython Main Window")
## Add a vertical box and a button
box = VBox();
ok_btn = Button("Ok")
ok_btn.Clicked += OnButtonClick
box.PackStart(ok_btn, False, False, 0)
wnd.Add(box)
## Set up the window delete event and display it
wnd.DeleteEvent += OnDelete
wnd.ShowAll()
## And we're off!...
Application.Run();
if __name__ == "__main__":
RealEntryPoint()
view raw gistfile1.py hosted with ❤ by GitHub

where the dynamic nature of the language means we can lose a lot of the declaration clutter. We just have to explicitly reference the main GTK# assembly (which is GAC'd by the GTK# installer), and away we go.

F# was almost, but not quite, as smooth. You have to add references to additional assemblies atk-sharp and glib-sharp, and the types are a little more explicit:

open System
open Gtk
let mutable click_count = 0
let OnClick (btn : Button) =
click_count <- click_count + 1
// Console.WriteLine("Button Click {0}", click_count)
btn.Label <- String.Format("Button Click {0}", click_count)
let OnDelete (sender:obj) (args:DeleteEventArgs) =
Application.Quit()
args.RetVal <- true
[<EntryPoint>]
let main a =
// Create the window
Application.Init();
let wnd = new Window("F# Main Window")
// Add a vertical box and a button
let box = new Gtk.VBox()
let ok_btn = new Button("Ok")
//ok_btn.Clicked += new EventHandler(OnButtonClick)
ok_btn.Clicked.AddHandler(fun s a -> OnClick ok_btn)
box.PackStart(ok_btn, false, false, (uint32 0))
wnd.Add(box)
// Set up the window delete event and display it
wnd.DeleteEvent.AddHandler(fun s a -> OnDelete s a) // fun still needed
wnd.ShowAll()
// And we're off!...
Application.Run()
0
view raw gistfile1.fs hosted with ❤ by GitHub

With the project built as a Windows Application, the Console output doesn't show (even to the Output window in Visual Studio), so the code has been changed to update the button caption after clicking. Apart from that, GTK# follows the WinForms eventing model, so wiring up the events is just a matter of adding the appropriate handler functions in the same way as you would normally -- including the effect that the function value OnDelete needs to be coerced to a delegate type of the same signature such as via a wrapper fun as shown, and can't just be added directly.

This program is also not FxCop clean, but there's nothing GTK# specific about the tidying operations required.

As expected, these work unchanged with the 1.9.9.9 CTP

No comments :