![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Sather の開発が停滞していることもあり、機能はそれほど豊富ではありませんが、普通の GUI を作る分には十分でしょう。 ネイティヴコードにコンパイルされるので、Tcl/Tk, Python/Tk などと比べて実行速度は格段に速いです。
また、デモスクリプトが $SATHER_HOME/Library/System/Gui/Demos にあります。 Doc.fmk.ps の 2 頁に プログラム名と main のあるクラス名が載っている表があるので、それをみてコンパイルします。 例えば、pizza.sa は次のようにコンパイルします。コンパイルの際に -gui オプションをつけます。
sacomp -gui -main PIZZA_MAIN -o pizza pizza.saコンパイルすると山ほど Warning が出ますが、無事実行ファイルができます。 pizza を実行すると図1のような Widget が現れます。ピザの種類、サイズ、トッピングを選択すると値段が表示されます。
図1:pizza の実行画面
[code 1]: tkhello.sa
01: -- a simple Tk hello world. 02: 03: class MAIN is 04: include GUI_UTIL; -- このクラスを include すると init だけ自分で定義すれば GUI プログラムが書けます。 05: 06: init is 07: label::=#TK_LABEL(root_window,TK_LABEL_CFG::std.text("Hello World!")); -- 下記参照 08: end; 09: end;コンパイルして実行すると図2のような Widget が表示されます。
$ sacomp -gui tkhello.sa -o tkhello $ ./tkhello
図2: Sather/Tk を使った簡単な Hello World。
メソッド、変数 | 説明 |
---|---|
(stab) init | プログラマーはこの部分を自分で書く必要があります。 |
root_window | トップレベルの widget です。 |
packer | widget を pack するときに使います。TK_PACK::create と同じです。 |
quit_routine | プログラムを終了するための ROUT です。 |
main | 通常はいじる必要はありません。 |
startup_gui | Widget を作ります。通常は使いません。 |
gui_loop | イベントを待ちます。通常は使いません。 |
図3:文字色と背景色が入れ替わる Hello World。
01: -- a simple Tk hello world with toggle button. 02: 03: class MAIN is 04: include GUI_UTIL; 05: 06: private attr label:TK_LABEL; -- Hello World を表示するラベル 07: private attr label_config:TK_LABEL_CFG; -- ラベル設定クラスのインスタンス 08: private attr black_foreground:BOOL; -- 黒文字のとき true 09: 10: toggle is -- ラベルの白黒を入れ替えるメソッド 11: if black_foreground then 12: label.configure(label_config.foreground("white").background("black")); -- configure メソッドを使って設定を変える。 13: black_foreground:=false; 14: else 15: label.configure(label_config.foreground("black").background("white")); 16: black_foreground:=true; 17: end; 18: end; 19: 20: init is -- 初期設定メソッド 21: label_config:=#; 22: label:=#(root_window, 23: label_config.text("Hello World!").padx(6.0).pady(6.0).foreground("black").background("white"), 24: packer.top_grow_horiz_n_vert.anchor(TK_ANCHOR::center)); 25: frame::=#TK_FRAME(root_window, packer.bot); 26: 27: button1::=#TK_BUTTON(frame, 28: TK_BUTTON_CFG::std.text("EXIT").padx(6.0).pady(6.0), 29: packer.left); 30: button1.command(quit_routine); 31: 32: button2::=#TK_BUTTON(frame, 33: TK_BUTTON_CFG::std.text("TOGGLE").padx(6.0).pady(6.0), 34: packer.right); 35: button2.command(bind(toggle)); 36: black_foreground:=true; 37: end; 38: end;
メソッド | 説明 |
---|---|
top | widget を上に配置します。 |
top_grow_horiz | 上に配置して横に伸ばします。 |
top_grow_horiz_n_vert | 上に配置して上下左右に伸ばします。 |
top_n_grow_vert | 上に配置して上下に伸ばします。 |
bot | widget を下に配置します。 |
bot_grow_horiz | 下に配置して横に伸ばします。 |
bot_grow_horiz_n_vert | 下に配置して上下左右に伸ばします。 |
bot_n_grow_vert | 下に配置して上下に伸ばします。 |
left | widget を左に配置します。 |
left_grow_vert | 左に配置して上下に伸ばします。 |
left_grow_vert_n_horiz | 左に配置して上下左右に伸ばします。 |
left_n_grow_horiz | 左に配置して左右に伸ばします。 |
right | widget を右に配置します。 |
right_grow_vert | 右に配置して上下に伸ばします。 |
right_grow_vert_n_horiz | 右に配置して上下左右に伸ばします。 |
right_n_grow_horiz | 右に配置して左右に伸ばします。 |
external_padding(x, y:FLT) | 上下左右のマージンを設定します。 |
internal_padding(x, y:FLT) | 上下左右のパディングを設定します。 |
anchor(a:TK_ANCHOR) | 配置の微調整をします。 |
メッソド | 説明 |
---|---|
center | 配置可能範囲の中央に配置します。 |
n | 配置可能範囲の上に配置します。 |
nw | 配置可能範囲の左上に配置します。 |
w | 配置可能範囲の左に配置します。 |
sw | 配置可能範囲の左下に配置します。 |
s | 配置可能範囲の下に配置します。 |
se | 配置可能範囲の右下に配置します。 |
e | 配置可能範囲の右に配置します。 |
ne | 配置可能範囲の右上に配置します。 |
[code 2] のプログラムは図4に示すようにラベルが伸縮し、Hello World が常に中央に表示されます。
図4:button_hello の widget を引き伸ばしたところ。
図5:ラジオボタンで文字色と背景色が選択できる Hello World。
[code 3] にソースコード (radio_hello.sa) を示します。
01: -- a simple Tk hello world with radio buttons. 02: 03: class MAIN is 04: include GUI_UTIL; 05: 06: private const fgcolors:ARRAY{STR}:=|"white","black", "red", "blue", "yellow"|; -- 文字色 07: private const bgcolors:ARRAY{STR}:=|"whitesmoke", "dimgray", "salmon", "skyblue", "lightyellow"|; -- 背景色 08: private attr label:TK_LABEL; 09: private attr label_config:TK_LABEL_CFG; 10: private attr fg:TK_VAR; 11: private attr bg:TK_VAR; 12: 13: config_label is 14: label.configure(label_config.foreground(fg.query).background(bg.query)); 15: end; 16: 17: rbuttons(name:STR, colors:ARRAY{STR}, fr:TK_FRAME, v:TK_VAR, default:STR) is -- ラジオボタンのセットを作るメソッド 18: s:STR; 19: r::=#TK_LABEL(fr, TK_LABEL_CFG::std.text(name), packer.top); 20: loop 21: s:=colors.elt!; 22: b::=#TK_RADIO(fr, 23: TK_RADIO_CFG::std.text(s).variable(v).val(s), 24: packer.top.anchor(TK_ANCHOR::w)); 25: b.command(bind(config_label)); 26: if s=default then b.select; end; -- select メソッドで最初に選択されるボタンを指定します。 27: end; 28: end; 29: 30: 31: init is 32: label_config:=#; 33: fg:=#; 34: bg:=#; 35: label:=#(root_window, 36: label_config.text("Hello World!").padx(6.0).pady(6.0).foreground("black").background("white"), 37: packer.top_grow_horiz_n_vert.anchor(TK_ANCHOR::center)); 38: frame::=#TK_FRAME(root_window, packer.bot); 39: 40: -- creating radio buttons 41: fconfig:TK_FRAME_CFG:=TK_FRAME_CFG::std.borderwidth(3.0).relief_ridge; 42: rbuttons("foreground", fgcolors, #TK_FRAME(frame, fconfig, packer.left), fg, "black"); -- 文字色を選ぶラジオボタンを作成 43: rbuttons("background", bgcolors, #TK_FRAME(frame, fconfig, packer.right), bg, "whitesmoke"); -- 背景色を選ぶラジオボタンを作成 44: end; 45: end;
図6:TK_CANVAS を使った Hello World。キャンバス上でマウス左クリックすると文字列がそこに移動する。
[code 4] にソースコード (canvas_hello.sa) を示します。
[code 4] canvas_hello.sa
01: -- a simple Tk hello world with Tk canvas 02: 03: class MAIN is 04: include GUI_UTIL; 05: 06: private attr cvs:TK_CANVAS; 07: private attr tag:TK_CANVAS_TAG; 08: private attr atag:ARRAY{TK_CANVAS_TAG}; 09: 10: mv(a:TK_EVENT_INFO) is -- マウス左クリックで Hello World を動かす関数 11: cvs.delete(tag); -- もともとあった Hello World を消す。 12: x,y:INT; 13: a.mouse_coordinates(out x, out y); -- マウスの位置を取得 14: cvs.draw_text("Hello World! @(" + x + "," + y + ")", 15: x.flt, y.flt, atag, TK_CTEXT_CFG::std.fill("navy")); -- そこに新たに Hello World を表示する。 16: end; 17: 18: rd(a:TK_EVENT_INFO) is 19: cvs.text_configure(tag, TK_CTEXT_CFG::std.fill("red")); -- 文字色を赤にする 20: end; 21: 22: nv(a:TK_EVENT_INFO) is 23: cvs.text_configure(tag, TK_CTEXT_CFG::std.fill("navy")); -- 文字色を Navy にする。 24: end; 25: 26: init is 27: dummy:$OB:=void; -- タイトルバーにタイトルを表示するにはこのおまじないが必要(いまいちダサい) 28: TK_WINDOW_MGR::title(root_window, "Hello World! on Tk Canvas"); -- タイトルバーにタイトルを表示する。 29: tag:=#; 30: atag:=#(|tag|); 31: cvs:=#(root_window, -- スクロールバー無しのキャンバスを作る。 32: TK_CANVAS_CFG::std.background("cornsilk").hscroll(false).vscroll(false).scroll_region(0.0,0.0,200.0,200.0)); 33: cvs.draw_text("Hello World! @(100.0,100.0)", 100.0, 100.0, atag,TK_CTEXT_CFG::std.fill("navy")); -- Hello World を (100,100) に描く。 34: cvs.bind_event(TK_BUTTON_EVENT::B1, bind(mv(_))); -- マウス左クリックで mv が呼ばれる。 35: cvs.bind_event(TK_EVENT::Widget_enter, tag, bind(rd(_))); -- マウスが文字列に入ると rd が呼ばれる。 36: cvs.bind_event(TK_EVENT::Leave, tag, bind(nv(_))); -- マウスが文字列から出ると nv が呼ばれる。 37: end; 38: end;
オブジェクト | 設定クラス |
---|---|
線 | TK_LINE_CFG |
楕円 | TK_OVAL_CFG |
多角形 | TK_POLY_CFG |
長方形 | TK_RECT_CFG |
文字列 | TK_CTEXT_CFG |
window | TK_CWIND_CFG |
図7:TK_TEXT を使ったファイル内容の表示。
コード (tkmore.sa) を [code 5] に示します。
[code 5] tkmore.sa
01: -- a simple Tk version more 02: 03: class MAIN is 04: include GUI_UTIL main->; 05: 06: private attr s,fn:STR; 07: 08: main(av:ARRAY{STR}) is -- 引数をとるように main を書き換える 09: if av.size=2 then 10: fn:=av[1]; -- av[1] で与えられたファイルを開いて、 11: f::=FILE::open_for_read(fn); 12: if f.error then 13: #ERR + "Cannot open " + fn +"\n"; 14: UNIX::exit(1); 15: else 16: s:=f.str; -- その内容を読み込んで、 17: f.close; -- ファイルを閉じる 18: GUI_APP_END::startup; 19: init; 20: GUI_APP_END::main_loop; 21: end; 22: else 23: #ERR + "Usage: tkmore FILENAME\n"; 24: end; 25: end; 26: 27: init is 28: dummy:$OB:=void; 29: TK_WINDOW_MGR::title(root_window, fn); -- タイトルバーにファイル名を表示する。 30: txt::=#TK_TEXT(root_window, TK_TEXT_CFG::std.hscroll(false).background("ivory")); -- 水平スクロールバーなしの TK_TEXT を作る。 31: txt+s; -- ファイルの内容を表示するのは '+' を使えばよい。 32: end; 33: end;
コンパイルして実行すると図7に示した画面が現れます。実行速度が速く、意外と便利なソフトです。
$sacomp -gui -o tkmore tkmore.sa $./tkmore tkmore.sa
さらに詳しい情報は Sather Class Index などをみてください。 また、付録にここで示したコードをつけておきます。
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |