概要
for文を用いてwidgetを作成した際、各widgetに対して異なる操作をする方法
How to operate "bind" function when I make widgets by for loop
コード例
for文でボタンを作成
placing the button widget by for loop
set value {red blue}
foreach val $value {
button ".bt$val" -text $val -fg gray -command "assign $val"
pack .bt$val
}
proc assign {val} {
puts $val
.bt$val configure -fg $val
}
中括弧{} ではなくダブルクオート"" を用いることでローカル変数valが即時に(定義時に)評価されます。
tcl evaluate inside of quote "" while definition. brace {} deffer the evaluation.
OOP例
tclのバインドで気をつけなければいけないところは、バインドが参照するスコープはパブリックスコープということです。
つまりローカル変数は参照できません。そのためクラスなどを用いるときは工夫が必要となります。以下に一例を載せますが、より良い方法があれば教えて欲しいです。(namespace の使い方などはあまり理解していないので良い参考文献等あれば知りたいです)
Note that the bind function of tcl/tk reffer the public scope. Therefore you can never reffer the local variable. Thus we have to think out how to implement. I show a example below. (If there is a better way, please ask me. and I want to know the detail of "namespace", so let me know the reference of that)
set value {red blue}
oo::class create Window {
constructor {} {
my make_button
}
method make_button {} {
global value
foreach val $value {
button ".bt$val" -text $val -fg gray -command "assign \$window $val"
pack .bt$val
}
}
method change_fg color {
.bt$color configure -fg $color
}
}
proc assign {window color} {
$window change_fg $color
}
set window [Window new]
ここで注意して欲しいのが、ローカル変数valは定義時に参照するのに対し、インスタンスwindowは呼び出しのタイミングで参照する必要がある。従ってバックスラッシュ"¥"を用いることで評価するタイミングをずらした。
Note that I reffer the instance "window" at the time the bindng invoked, in constant I reffer the local variable val while definition. I use the backslash "¥" before $ so that prevent from evalating in defenition.
まとめ
tcl/tkは世界的にはある程度使われているが、日本語のレファレンスが圧倒的に少ないデメリットがある。
tcl/tk のバインドはパブリックスコープを参照する都合上pythonのtkinterと比べクラスの扱いが難しくなっている。
そのため前述したnamespaceを活用した方法がよく見られる。そこについても調べていきたい。