キャンバスウィジェットでお絵描き
| 
キャンバスウィジェットを作成し それに線を引いてみる.  | 
|---|
まずは,キャンバスウィジェットを作成する.ここの例は簡単なので wish コマ ンドを対話的に起動して1行ずつ実行していくとその動作がわかりやすいだろう.
canvas .c -width 500 -height 500 pack .c  | 
|---|
これで,ウィンドウが開かれる.横幅と縦幅をそれぞれ 500 とした.".c" とい うのがウィジェットの名前で,ここではとても簡単なものにしている.これに線 を引いたりする命令 (コマンド) を渡すには,"ウィジェット名 コマンド コマ ンドオプション..." の形式をとる.ここでの「コマンド」は「ウィジェットコ マンド」と呼ばれる.線を引く場合は ".c create line x0 y0 x1 y1 ...." と なる."xN yN" の項は2つ以上の座標の組を指定する.これを使ってさきに開い たキャンバスに斜めに線を引くと次のようになる.
.c create line 0 0 500 500  | 
|---|
coords というウィジェットコマンドがあって,これを使うと生成したウィジェッ ト内のアイテムの座標を変更することができる.さきほど引いた線もキャンバス 内アイテムで座標を変えて表示することができる.アイテムは生成毎に ID (番 号) が割りふられているので,これを元に変更する座標を指定する.
set l_id [.c create line 0 0 500 500] .c coords $l_id 50 50 450 450  | 
|---|
set width 500
set height 500
set max 50
set r 200
set pi [expr atan2(1,1)*4]
set update 100
canvas .c -width $width -height $height
pack .c
bind . <q> {exit}
set x0 [expr $width/2 ]
set y0 [expr $height/2]
set i 0
set l_id [.c create line $x0 $y0 [expr $x0+$r] $y0]
while {1} {
  set th $i*2*$pi/$max
  set x [expr $x0+$r*cos($th)]
  set y [expr $y0-$r*sin($th)]
  .c coords $l_id $x0 $y0 $x $y
  update
  after $update {incr i}
  tkwait variable i
  if {$i>=$max} {set i 0}
}
 | 
|---|
動きをもう少し複雑にした例が circular.tk にあ る.興味があれば参考にするといいだろう.
coords コマンドは便利ではあるが,その生成 ID を保存し参照しなければなら ないので,図形エディタなどとは性質の異なるデータプロットアプリケーション などを作成する場合には,かえって処理が煩雑になる可能性がある.この場合に は毎回新たに与えられるので,coords で座標更新を行う恩恵がそれほど得られ ないからだろう.だから,データ点列を多数プロットする場合には,毎回 ".c delete all" などですべてをきれいに削除して,一から描き直すのがいいようで ある.
scale ウィジェット名 \ -from 開始値 -to 終端値 \ -variable 対応変数名 -command 更新時の呼び出し関数名  | 
|---|
これを使うとマウスを使って対話的に表示角度を指定することができる.プログ ラム例は次のようになる.ここでの線の表示更新は,"delete all" ですべてを 削除してから新たに作成し直すことで行った.
set width 500
set height 500
set pi [expr atan2(1,1)*4]
set deg2rad [expr $pi/180]
set r 200
proc plotLine {{w} {x1} {y1} {x2} {y2}} {
  global width height
  set x1 [expr $width/2+$x1]
  set y1 [expr $height/2-$y1]
  set x2 [expr $width/2+$x2]
  set y2 [expr $height/2-$y2]
  $w create line $x1 $y1 $x2 $y2
}
proc rotateLine {{w}} {
  global th r
  global deg2rad
  $w delete all
  set tmp [expr $th*$deg2rad]
  set x [expr $r*cos($tmp)]
  set y [expr $r*sin($tmp)]
  plotLine $w 0 0 $x $y
}
canvas .c -width $width -height $height
scale .scl -from "-180" -to 180 \
  -variable th -command "rotateLine .c; set null"
pack .c .scl -side left -fill y -expand yes
bind . <q> {exit}
 | 
|---|

proc calcAngle {{x} {y}} {
  global width height
  global deg2rad
  return [expr atan2($height/2-$y, -$width/2+$x)/$deg2rad]
}
bind .c <Button-1>       {set th [calcAngle %x %y]; rotateLine .c}
bind .c <Button1-Motion> {set th [calcAngle %x %y]; rotateLine .c}
 | 
|---|
ここまでに見てきたように Tcl/Tk を使うと変数の内容を設定したり,その内容 を変更したりすることが対話的に実現可能(ということは変更が簡単)なので, 多数の設定パラメータを持つシミュレータなどでの利用にその効果が期待され る.
bind . <Alt-p> {.c postscript -file "tmp_canvas.ps" -colormode color}
 | 
|---|
出力形式は現在のところ PostScript しか存在しないが,外部コマンドの pstoedit を使用することで,Tgif/GNUPLOT/JavaApplet などの各種形式へと変 換することが可能である.(ただし,pstoedit は特定のフォントセットの設定 にしか対応していないので日本語 Tcl/Tk から生成された PostScript だと,文 字も図形として処理されてしまう.非日本語化 Tcl/Tk を使う必要がある.そも そも,canvas ウィジェットから出力される PostScript が日本語対応していな かったかも..??).