BLTの棒グラフ

 BLTのグラフはどれもものすごい数のオプションがあるので、 それらを全部並べていると途中で飽きてしまいます。 それはやめといて、 折れ線グラフのところで紹介したのをもう一度整理して最初から今度は棒グラフを描いてみましょう。

package require BLT
namespace import blt::*
namespace import -force blt::tile::*
wm title . "BLTのサンプル3"

set xdata {1 2 3 4 5}
set ydata {65 30 40 90 55}

barchart .sc \
 -plotbackground "#c0c0c0" -plotrelief sunken \
 -plotborderwidth 2 -background "#808080" \
 -relief groove -bd 2 -title "My Brain is Compact"

.sc element create ELEMENT1 \
  -xdata $xdata -ydata $ydata -label "This is the Legend" -fg "#700040"

proc getSubjectByID {sc value args} {
    set subjects {dummy 国語 数学 物理 地理 英語}
    return [lindex $subjects $value]
}

.sc axis configure x -color white -command "getSubjectByID" \
        -title 教科 -titlecolor "#c0c0c0"

.sc axis configure y -color white -min 0 -max 100

.sc legend configure -position right -relief groove -font 7x14 -fg #000060

.sc crosshairs configure -hide no -color black -linewidth 2 -dashes ""
Blt_Crosshairs .sc

.sc grid configure -hide no -color "#808080" -dashes {1 4 1}

image create photo Image1 -file copy.gif
for {set i 0} {$i<[llength $xdata]} {incr i} {
    set lab [label .sc.lab$i -image Image1]
    .sc marker create window \
        -coords [list [lindex $xdata $i] [expr [lindex $ydata $i]-5] ] \
        -anchor n -window $lab
}
pack .sc -side top
button .cmda -text 閉じる -command exit
pack .cmda -anc e -padx 4 -pady 4

まずBLTのライブラリをロードします。

package require BLT
namespace import blt::*
namespace import -force blt::tile::*

データはこんな感じです。
国語 数学 物理 地理 英語
65 30 40 90 55
うわあ、落ちこぼれ。誰ですかこれは。それはひとまずおいといて、 このように、片軸が数値軸でない場合には、少し仕掛けが必要です。 とりあえずデータはこのようにしておきます。

set xdata {1 2 3 4 5}
set ydata {65 30 40 90 55}

まず、barchartコマンドで棒グラフを描く範囲を普通のTk部品と同じようにして作ります。

barchart .sc \
 -plotbackground "#c0c0c0" -plotrelief sunken -plotborderwidth 2 \
 -background "#808080" -relief groove -bd 2 \
 -title "My Brain is Compact"

このように生成時に全オプションを定義することもできますが、 他にも

barchart .sc
# ...
.sc configure -plotbackground "#c0c0c0" \
              -plotrelief sunken \
              # ...

このように後で configure サブコマンドを使ってオプションを何度でも追加したり、 変更したりできます。つまり普通のTk部品と同じ cget & configure で操作できるわけですね。 ちなみに -plotbackground, -plotrelief, -plotborderwidth というのはグラフの描画範囲の色や周囲の描き方を指定するオプションで、 -background(-bg), -relief, -borderwidth(-bd) はその周囲の領域の描き方を指定するオプションです。 というか使ってみればすぐにわかるので、細かいうだうだはここでは省きますね。

 次にグラフの「データ系列」を作ります。 データ系列とは、ようするにグラフのデータを表現するもの、 棒グラフなら棒、折れ線グラフなら折れ線です。 これは下の ELEMENT1 など適当な名前を決めて、「element create」サブコマンドで行います。

.sc element create ELEMENT1 \
  -xdata $xdata -ydata $ydata -label "This is the Legend" -fg "#700040"

ここでデータ-xdata, -ydata にデータ(数値のリスト)を指定することで、実際に描画に反映させます。 X軸にご注意! X軸のデータがたとえ「国語」「数学」のような非数値軸の場合でも、 ここでは必ず数値軸としてなんでもいいから数値からなるリストを指定しなくてはいけません。 上では $xdata として {1 2 3 4 5} のようなデータを仮に入れてあります。

 ちなみにこの elementも、一旦 element create サブコマンドで作ったあとに、 「element configure」サブコマンドを使って

.sc element configure ELEMENT1 -fg "#700040"

このようにしてオプションを追加したり変更したりできます。 以後のaxis、crosshairs、grid、marker…などもすべて要領はこの element と同じで、ただオプションの種類が違うだけです。

次にX軸を作りましょう。 ここで先ほどの {1 2 3 4 5} を {国語 数学 物理 地理 英語} に読みかえる処理を行っています。

proc getSubjectByID {sc value args} {
    set subjects {dummy 国語 数学 物理 地理 英語}
    return [lindex $subjects $value]
}

.sc axis configure x \
  -color white -command "getSubjectByID" \
  -title Subject -titlecolor "#c0c0c0"

axis はデフォルトで「x」と「y」というのができているので、 「axis create」などとする必要はなく、いきなり 「axis configure x」でオプションを後に続けますが、 ポイントは -command "getSubjectByID" というところです。-command を指定すると、X軸に -xdata で与えられた数値の配列の代わりに、 このコマンドを呼び出して返される文字列が書かれます。 このコマンドの後ろには、このbarchart部品の名前(上では.sc)と現在の数値が引数として自動的につけられます。 これでX軸には {1 2 3 4 5} の代わりに {国語 数学 物理 地理 英語} が表示されることになります。

 Y軸のほうもやり方はまったく同じです。ここでは、-min と -max を指定して描画するグラフの値の範囲を指定しています。 この -min と -max を広げたり狭めたりすることで、 ズームイン・ズームアウト機能を簡単につけることができます。

.sc axis configure y -color white -min 0 -max 100

 レジェンドとは普通伝説という意味ですが、ここでは「凡例」 の意味です。legendの原義は「読まれるもの」だそうで。 なるほど、読まれるもの=凡例ですか。 凡例に出す各データ系列の説明は、 element configureサブコマンドの -label オプションで指定します。 この legend configureサブコマンドは、 凡例を表示する長方形の領域の描き方を指定するものです。

.sc legend configure \
  -position right -relief groove -font 7x14 -fg blue

 クロスヘアというのは前のページにも出てきたとおり、 マウスがグラフの上を走るとそれについて十字に動く交差線のことです。 クロスヘアは、「表示しない」のがデフォルトになっていて、 表示するためには「-hide」オプションを「no」 にする必要があります。このひねくれ者ー。

.sc crosshairs configure \
  -hide no -color black -linewidth 2 -dashes ""
Blt_Crosshairs .sc

また、クロスヘアを実際に表示するためには、なぜか Blt_Crosshairs という低位のライブラリプロシージャを上のように呼び出す必要があります。

 グリッドはペイントツールやドローツールでおなじみの方眼です。 これも表示しないのがデフォルトなので、やはり「-hide no」 と指定しなければ表示されません。クロスヘアのオプションにもありましたが、 -dashes というのは点線(破線)の「破れ具合」を指定するものです。 言葉ではムッチャ説明しづらいので、適当に数値を変えて試してみてください。 -dashes "" とすると、実線での表示になります。デフォルトはこの実線です。

.sc grid configure \
  -hide no -color "#808080" -dashes {1 4 1}

 最後に大物マーカーが残りましたが、これは感覚的にはキャンバス部品(canvas) のように、グラフの描画領域の中に長方形や円などの線図形、 テキスト、画像、それに他のTk部品を配置することができるものです。 下の例では、各棒の頭の部分に、 画像データを貼り付けたラベルを載せています。

image create photo Image1 -file copy.gif
for {set i 0} {$i<[llength $xdata]} {incr i} {
    set lab [label .sc.lab$i -image Image1]
    .sc marker create window \
        -coords [list [lindex $xdata $i] [lindex $ydata $i]] \
        -anchor n -window $lab
}

最後にこの .sc をpackなどで載せると棒グラフのできあがりです。

pack .sc -side top
button .cmda -text Close -command exit
pack .cmda

できばえはこんな感じです。


Tk部品に壁紙を貼る

 BLTでは、ラベル、ボタン、チェックボタン、ラジオボタン、 フレーム、スクロールバー、トップレベルの背景に photoイメージの壁紙をはりつけることができるように拡張されています。 使い方は簡単、-tileオプションでイメージの名前を指定するだけです。

package require BLT
namespace import blt::*
namespace import -force blt::tile::*

wm title . {nihon kabegami international}
image create photo Image1 -file indexbanner.gif
image create photo Image2 -file copy.gif
frame .f -tile Image1
message .f.ma -text {Hello. This is a sample of tile-extended widgets.} \
  -fg #700040 -font {Helvetica 12 normal}
button .f.cmda -text OK -command exit -tile Image2
pack .f.ma   -side top -padx 4 -pady 4
pack .f.cmda -side top -ipadx 10 -padx 4 -pady 4
pack .f

この機能を効果的に使うと、あなたのアプリケーションが超極美麗に早変わり。

BLTの壁紙機能のサンプル

ただし、センスがないと上のようになります。フギャ。


BLTのスナップショット機能

 BLTには、Tcl/Tkのウィンドウのスナップショットを取り、 Tkのphotoイメージにコピーする機能があります。 キャンバスに描画した図形をビットマップで保存でき、とても便利です。

package require BLT
namespace import blt::*
namespace import -force blt::tile::*

canvas .can -bg white
.can create polygon {20 30 40 80 60 90 90 75 50 40 20 30} \
  -outline yellow -fill red -tag TagPolygon
.can create oval 100 80 130 110 -outline blue -fill cyan -width 5 -tag TagOval
foreach t {TagPolygon TagOval} {
    .can bind $t <Button-1> { set StartX %x ; set StartY %y }
    .can bind $t <Button1-Motion> "
      set dx \[expr %x-\$StartX\]; set dy \[expr %y-\$StartY\]
      set StartX %x; set StartY %y; %W move $t \$dx \$dy"
}
pack .can
bind .can <Button-3> {
    image create photo Image1
    winop snap . Image1
    Image1 write output.gif -format gif
    image delete Image1
}
# end.

 スナップショットを取るのはwinop snap というコマンドで、引数に取りたいウィンドウと、取ったイメージを保存したい Photoイメージの名前を指定すればOKです。

    winop snap . Image1

 上の画像は、本当にこの方法でGIF画像ファイルとして保存したものです。 本当です。この程度の画像、ウソでも本当でも大差ないのですが、 そこでわざわざこの方法でスナップショットをとるのが筋というもの、 と、さも漢(おとこ)のこだわりとゆーものを感じさせてみようとしたり(帰れ)

拡張レビュー分室 top
(first uploaded 1999/11/12 last updated 2002/03/09, KAZUHISA ESHI - MISUMI URANO)