エレクトロニクスセミナー
Tcl/Tkの学習


  

  1. TCl/Tkの利用法

    詳しくは専門書を参考する必要があるが、今回はあらかじめ決められた手順のスクリプトを用いて、実際に Tcl/Tkを利用してプログラムを行う。まずは、Kterm 上で


    wish

    と入力する。すると、画面に小さな窓があらわれ、Kterm上のプロンプト(コマンド待ちの記号)が%に変わる。ここでは、WIndow SHellというシェル(ユーザとOSの仲立ちをしてくれる環境であり、MacであればFinderの様なもの)を使って、GUI (Graphical User Interface) を利用しながらプログラミングを行なえるようになっている。

    以下のような文字を%のプロンプトが表示されているKterm上に入力する。ただし、%はプロンプト記号を表しており、入力の必要は無い。

    %button .b0 -text "Button" -command "exit"
    %pack .b0

    さて、結果はと言うと、先ほど現れたウィンドウが小さくなり、Button と書かれたボタンが出現するはず。マウスでそのウィンドウを選択し、ボタンをクリックするとウィンドウが消える。

    大雑把に言うと、コマンドを打ち込んだのが Tcl という言語であり、ウィンドウが Tk というツールキットになっている。wishを実行すると、tclというシェルtclsh が起動し、ウィンドウが開く。%はtclshというシェルのプロンプトである。

    通常のKtermではbashというシェルが動作しており、プロンプトは$マークである。

    上で実行したプログラムはButton というテキストを持つボタンでそれを押した時に実行するコマンドはexitである、そういう図形をウィンドウ内にpackしなさい、という内容であった。毎回コマンドを入力しながら実行するのは効率が悪いので、次にスクリプトを書く方法を紹介する。


  2. スクリプトの作成

    先ほどと同様の作業を行うために、Emacsに移る。一番上から以下のようなテキストを入力する。

    #!/usr/bin/wish
    button .b0 -text "Button" -command "exit"
    pack .b0

    次にこの内容をmybuttonという名前で保存する。その後、Ktermに戻り以下のコマンドを入力し、Enterキーを押す。

    chmod +x myboutton

    このコマンドはファイルの属性に実行権限を与えるもの(モードをチェンジする)であり、スクリプトファイルであることを宣言している。実際に実行するためには、Ktermにおいて、

    ./mybutton

    と入力する。さて、上手く動作しただろうか?

    このように、あらかじめ用意されているGUIツールを並べて動作を指定することによりプログラムを作成するのが、Tcl/Tkである。本来ならば、ここで各種のツールに関して詳細な説明をしないと、実際に使用できるようなアプリケーションはできないが、時間の制約もあるので、内容はおいておき、各種のプログラムを書いて行く。興味があれば、自分で勉強するなどして欲しい。


  3. ○×ゲームの作成

    以下に示す内容を、mygameと言う名前でEmacs上で作成する。ファイルメニューから新規ファイルを選んでmygameと言う名前を付けてから入力を始める。また、このwebページから○と×の絵をダウンロードして使っても良いし、自分でThe Gimpなどを使ってcircle.gifやcross.gifを作成してもよい。

    #!/usr/bin/wish
    . configure -width 256 -height 192
    image create photo maru -file circle.gif
    image create photo batu -file cross.gif
    image create photo blank -width 64 -height 64
    label .l0 -text "○か×\nを選択"
    checkbutton .c0 -image maru -selectimage batu \
    -indicatoron false -offvalue maru -onvalue batu -variable val
    button .b9 -text "終了" -command "exit"
    place .l0 -x 0 -rely 0.0 -relwidth 0.25 -relheight 0.333
    place .c0 -x 0 -rely 0.333 -relwidth 0.25 -relheight 0.333
    place .b9 -x 0 -rely 0.667 -relwidth 0.25 -relheight 0.333
    for { set i 0 } { $i < 9 } { incr i } {
    button .b$i -image blank -command ".b$i configure -image \$val"
    place .b$i -x [expr 64*($i/3)+64] -y [expr 64*($i%3)]
    }

    入力が完了したら、先ほどと同様にKtermで

    chmod +x mygame

    とし、実行権限を与えた後、

    ./mygame &

    としてプログラムを起動しよう。

           

    circle.gifのデモ用画像 cross.gifのデモ用画像

    上のような○の絵と×の絵を使って○×ゲームを行うプログラムである。左の○をクリックすると×にかわり、逆も同様である。人間どうしが対戦する形式の冴えないプログラムであるが、この程度のことがたった16行で書けると言うのも便利であることが実感できただろうか。

    さて、これ以降は時間の許す限りで良いので以下の入力を行うか、さらにその次の作業をするか自分で選んで欲しい。次に示すプログラムは時計を表示するものである。入力後は実行権限を与えるのを忘れないこと。

    このプログラムは終了ボタンが無いので、マウスによる操作では終了できません。

    #!/usr/bin/wish
    canvas .c0 -width 200 -height 200
    set s [.c0 create line 0 0 0 0 -width 4 -fill blue]
    set m [.c0 create line 0 0 0 0 -width 4 -fill green]
    set h [.c0 create line 0 0 0 0 -width 4 -fill red]
    pack .c0
    for { set i 0 } { $i < 60 } { incr i } {
    set dx [expr cos(3.1416*2*(15-$i)/60)]
    set dy [expr -sin(3.1416*2*(15-$i)/60)]
    set dd [format "%02d" $i]
    set secx($dd) [expr 100+$dx*90]
    set secy($dd) [expr 100+$dy*90]
    set minx($dd) [expr 100+$dx*80]
    set miny($dd) [expr 100+$dy*80]
    for { set k 0 } { $k < 24 } { incr k } {
    set dx [expr cos(3.1416*2*(3-$k+$i/60)/12)]
    set dy [expr -sin(3.1416*2*(3-$k+$i/60)/12)]
    set hh [format "%02d" $k]
    set hourx($hh.$dd) [expr 100+$dx*60]
    set houry($hh.$dd) [expr 100+$dy*60]
    }
    }

    proc showtime { } {
    global s m h secx secy minx miny hourx houry
    set c [clock seconds]
    set ss [clock format $c -format "%S"]
    set mm [clock format $c -format "%M"]
    set hh [clock format $c -format "%H"]
    .c0 coords $s 100 100 $secx($ss) $secy($ss)
    .c0 coords $m 100 100 $minx($mm) $miny($mm)
    .c0 coords $h 100 100 $hourx($hh.$mm) $houry($hh.$mm)
    after 1000 showtime
    }
    showtime


    4. 少し高度なプログラム例

    次のプログラムは簡単なテキストエディタとファイルマネージャである。簡単なプログラムで結構見栄えのよいものが作成できることを実感して欲しい。ここでも、ファイルマネージャに用いるアイコン画像はwebからダウンロードしても良いし、自分で作成してもよい。

    テキストエディタ起動コマンド

    ./myedit &

    ファイルマネージャ起動コマンド

    ./myfm &

    テキストエディタスクリプト
    #!/usr/bin/wish
    kanji defaultInputCode EUC
    text .t0 -width 50 -height 20 -yscrollcommand ".s1 set"
    scrollbar .s1 -orient vertical -command ".t0 yview"
    frame .f0

    menubutton .b0 -text "ファイル" -menu .b0.m0
    menu .b0.m0
    .b0.m0 add command -label "新規.." -command { .t0 delete 1.0 end}
    .b0.m0 add command -label "開く.." -command {
    .t0 delete 1.0 end
    set F [open [tk_getOpenFile]]
    while {[gets $F line]>=0} {.t0 insert end $line\n}
    close $F
    }
    .b0.m0 add command -label "保存" -command {
    toplevel .dialog
    label .dialog.l0 -text "保存先"
    entry .dialog.e0 -background white -textvariable Hozonsaki
    button .dialog.b0 -text "OK" -command {
    exec touch $Hozonsaki
    set fileID [open $Hozonsaki w]
    puts $fileID [.t0 get 1.0 end]
    close $fileID
    destroy .dialog
    }
    pack .dialog.l0 .dialog.e0 .dialog.b0
    }
    .b0.m0 add separator
    .b0.m0 add command -label "終了" -command {exit}

    pack .b0 -in .f0 -side left
    grid .f0 -row 0 -column 0 -columnspan 2 -sticky ew
    grid .t0 -row 2 -column 0 -sticky nsew
    grid .s1 -row 2 -column 1 -sticky ns
    grid rowconfigure . 2 -weight 100
    grid columnconfigure . 0 -weight 100


    ファイルマネージャの操作方法

    以下に示すスクリプトにより起動するファイルマネージャ(Windowsにおけるエクスプローラーのようなもの)はまだマウスによるフォルダのオープンなどはできない。上部の窓にあるディレクトリに文字で入力してそのディレクトリ内のファイルを表示する。ここで、フォルダのアイコンで示されるのが、ディレクトリであり、鉛筆は、実行プログラムを示す。最後に書類のアイコンは通常のファイルである。

      

    ファイルマネージャスクリプト
    #!/usr/bin/wish
    kanji defaultInputCode EUC

    set Crtdir [exec pwd]
    wm title . $Crtdir

    image create photo File_Icon -file Icon/File.gif
    image create photo App_Icon -file Icon/App.gif
    image create photo Folder_Icon -file Icon/Folder.gif

    proc GetInfo { } {
    global Crtdir FilenameList IconNum Filename IconImage

    set FilenameList [exec ls -F $Crtdir]
    set IconNum [llength $FilenameList]
    for { set i 0 } { $i < $IconNum } { set i [expr $i+1]} {
    set Filename($i) [lindex $FilenameList $i]
    image create photo IconImage($i)
    if { [ string first "/" $Filename($i) ] > -1 } {
    IconImage($i) copy Folder_Icon
    } else { if { [ string first "*" $Filename($i) ] > -1 } {
    IconImage($i) copy App_Icon
    } else {
    IconImage($i) copy File_Icon
    }
    }
    }
    }

    proc SetIconXY { } {
    global IconNum iconX iconY canvasY

    for { set i 0} { $i < $IconNum } { set i [expr $i+1]} {
    set iconX($i) [expr (100+15)*($i%4)+60]
    set iconY($i) [expr 80*($i/4)+45]
    }
    catch {
    set canvasY [expr $iconY([expr $IconNum-1])+70]
    } { set canvasY 500}
    }

    proc BuildGUI { } {
    global Crtdir canvasY

    canvas .c0 -width 500 -height 500 -yscrollcommand ".s1 set" -bg white -scrollregion " 0 0 500 $canvasY "
    scrollbar .s1 -orient vertical -command ".c0 yview"
    frame .f0
    entry .e0 -textvariable Crtdir
    pack .e0 -in .f0 -fill x
    grid .f0 -row 0 -column 0 -columnspan 2 -sticky ew
    grid .c0 -row 2 -column 0 -sticky nsew
    grid .s1 -row 2 -column 1 -sticky ns
    }

    proc DrawIcon { } {
    global IconNum Filename IconImage iconX iconY

    for { set i 0 } { $i < $IconNum } { set i [expr $i+1]} {
    .c0 create image $iconX($i) $iconY($i) -image IconImage($i)
    .c0 create text $iconX($i) [expr $iconY($i)+35] -text $Filename($i)
    }
    }

    proc Refresh { } {
    global canvasY
    GetInfo
    SetIconXY
    .c0 delete all ; .c0 configure -scrollregion " 0 0 500 $canvasY"
    DrawIcon
    }

    GetInfo
    SetIconXY
    BuildGUI
    DrawIcon

    bind .e0 <Return> {
    Refresh
    }


  4. 終わりに

    以上で本日のTcl/Tkの作業を終わる。Linuxの真価が発揮できるような高度なプログラミングはきちんと言語を学習しないと行なえないが、実際に使えるものを自分でプログラムすることの楽しさのようなものが感じられたとしたら、今回の目的は達成されている。ネットワークやゲームの端末としてのコンピュータだけではせっかくの性能が勿体無い。自分で少しずつプログラミングを覚えて行くことにより、コンピュータの世界は大きく広がることを知っておいて欲しい。


  5. 謝辞と参考文献

    本日のスクリプトの例は下記の文献から拝借しました。素晴らしい例題を作成してくれた方々に感謝します。

    久野靖、「入門Tcl/Tk」アスキー出版局、1997.
    宮脇大作、「Tcl/Tkで始める簡単GUIプログラミング」Linux Japan, August 1999, pp.126-135.

    宮脇大作、「Tcl/Tkで始める簡単GUIプログラミング」Linux Japan, September 1999, pp.123-129.


    2000.1.17講義内容へ戻る。