Canvas

Canvas は ListPlot などのプロットを表示する領域として用いられます。単なるグラフの表示ならば、ListPlot などを使うだけで充分なのですが、場合によっては Canvas に対して直接作用を及ぼす必要が生じます。例えば、描かれた図形の一部をクリックして何かある動作を行ったり、図形の移動や属性の変更を行うなどの仕事です。ここでは簡単な例をもとにこのような Canvas 特有の操作について説明します。

Canvasのアイテム

Canvas に描かれる部品はいくつかのアイテム(item)に分類されます。下の表はそれらのアイテムの一覧です。

アイテム描かれる図形
Arc扇形、弦、弓形
Bitmapイメージ
Line線分
Oval楕円
Polygon多角形
Rectangle長方形
Text文字列
Window他の部品をはめ込む枠

これらのアイテムは Canvas 上に例えば次のように作成されます。

FFS;

 w = Window[];
 c = Canvas[w, Width -> 300, Height -> 300];

 c[Create$Rectangle] = {50, 50, 250, 250, Tags -> "rectarc rectoval"};
 c[Create$Oval] = {50, 50, 250, 250, Fill -> "blue", Stipple -> "gray25", Tags -> "rectoval"};
 c[Create$Arc] = {50, 50, 250, 250, Style -> "pieslice", Fill -> "red", Start -> 60, Extent -> 90, Tags -> "rectarc"};

 TkWait[];

この例では Rectangle, Oval, Arc の3つのアイテムを下図のように描きます。

Canvas

このように、Canvas にあるアイテムを追加するには

Canvasシンボル[Create$アイテム] = {パラメータ1, ..., パラメータn,
 属性1 -> 値1, 属性2 -> 値2, ...}

のように書きます。ここで パラメータ1, ..., パラメータn, は一組またはそれ以上の座標です。これらは別々に書いても、リストにまとめても構いません。上の例では Create$Rectangle の 4 個の引き数がこのパラメータに当たります。次に属性の指定を必要に応じて行います。 パラメータ達は必ず属性の指定よりも先に書かなければなりません。

Canvasの座標

Canvas では座標の指定は Window の座標の指定と同様に左上隅を (0, 0) とし、右下に増加する座標で、単位はピクセルです。この座標と、CanvasDrawer の座標とは別のものなので、混同しないようにしてください。

アイテム番号

ひとつの Canvas に対して、製作された各アイテムには製作順にアイテム番号が自動的につけられます。この番号は 1 から順に 1 ずつ増加します。途中で Delete などの操作でアイテムが消去されても、同じ番号が再利用されることはありません。この番号は後に各アイテムに対して様々な操作を及ぼすときに使われます。

Tags

Canvas のアイテムには Tags という属性があり、各アイテムをグループに分けて、名称を付けることができます。これにより後でグループ毎に様々な操作を与えることが容易にできます。名称は空白、{}、() などを含まない任意の文字列です。

ひとつのアイテムが複数のグループに所属することも可能です。例えば上の例では、Rectangle には "rectarc" と "rectoval" の二つのグループが指定されています (書き方が多少妙ですがこうしてください)。

例えば、上の例でさらに

c[Move] = {"rectoval", 30, -20};
c[Update];
Canvas

Tagsでグループ化したアイテム達の移動。RectangleとOvalを含む グループ ( "rectoval") が(30, -20)だけ移動しました。

Arc

Arc は扇形、弓形、弧を描きます。Create$Arcはその Arc の弧を一部とする惰円の外接長方形の二つの対角頂点の座標を最初の 4 つのパラメータとします。

表にその属性を掲げます。

属性デフォルト効果
Extent角度(度)360弧の反時計方向の開き角
Fill無指定内部色
Outline"black"輪郭線の色
Start角度(度)0弧の開始角、反時計方向に計る
Stippleビットマップ塗りつぶしのビットマップ
Style"pieslice", "chord", "arc""pieslice"それぞれ扇形、弓形、弧の選択
Tags文字列そのアイテムにつけるタグ達
Width数値(ピクセル)1輪郭線の幅

また、次の例は図の様な結果になります。

 w = Window[];
 c = Canvas[w, Width -> 380, Height -> 140];
 styles = {"pieslice", "chord", "arc"};
 x = 20;
 Scan[
   (c[Create$Arc] = {x, 20, x + 80, 100,
     Style -> #, Fill -> "red",
     Start -> -30, Extent -> -120};
    c[Create$Text] = {x + 40, 120, 
      Text -> #};
    x += 120)&,
   styles];
Arc.jpg

Arcの3種のStyle

Bitmap

Bitmap は Canvas 上にビットマップ (\rref{bitmap} 参照) を表示します。Create$Bitmap} は位置をを指定するひと組の座標をパラメータとします。また、その座標と Bitmap との相対位置は属性 Anchor で指定します。Bitmap の属性は表に掲げます。

属性デフォルト効果
Anchor"c" "n" "ne" "e" "se" "s" "sw" "w" "nw""c"座標との相対位置
Background無指定背景色
Bitmapビットマップビットマップ (文字列または "@ファイル名")
Foreground"black"前景色
Tags文字列そのアイテムにつけるタグ達

Bitmapの属性

また、次の例は下の図を作ります。

w = Window[];
 c = Canvas[w, Width -> 600, Height -> 100];
 bitmap = {"error", "gray25", "gray50", "hourglass",
   "info", "questhead", "question", "warning"};
 x = 50;
 Scan[(
   c[Create$Bitmap]={x, 40, Bitmap -> #};
   c[Create$Text]={x, 70, Text -> "\""//#//"\""};
   x += 70)&,
   bitmap];
Bitmapbuiltin.jpg

Image

属性デフォルト効果
Anchor"c" "n" "ne" "e" "se" "s" "sw" "w" "nw""c"座標との相対位置
Imageイメージイメージ
Tags文字列そのアイテムにつけるタグ達

Imageの属性

Line

Line は折線を描きます。Create$Line} のパラメータは座標をa math image, ... と順に並べたものです。属性 Smooth が True のときは各点はスプライン曲線で結ばれ、False のときは直線で結ばれます。属性 CapStyle と JoinStyle は線分の端部と接合部の形状を指定します (図 \rref{lineexample} 参照) 。Line の属性は表 \rref{lineattrib} に掲げます。また、次の例は 図 \rref{lineexample} を作ります。

  w = Window[];
  c = Canvas[w, Width -> 640, Height -> 270];
  options = {
    CapStyle -> "butt",
    CapStyle -> "projecting",
    CapStyle -> "round",
    JoinStyle -> "bevel",
    JoinStyle -> "miter",
    JoinStyle -> "round"};
  {x, y} = {20, 90};
  Scan[(
    c[Create$Line] = {x, y, x + 110, y - 60, x + 180, y,
      Width -> 20, #};
    c[Create$Text] = {x + 90, y + 20,
      Text -> #[[1]]//" -> \""//#[[2]]//"\""};
    x += 210;
    If[x > 500, x = 20; y += 120])&,
    options];
属性デフォルト効果
Arrow"none" "first" "last" "both""none"矢頭の有無
ArrowShape{接続部長,全長, 全幅}矢頭の形状(ピクセル)
CapStyle"butt" "projecting" "round""butt"端部の形状
Fill"black"線の色
JoinStyle"bevel" "miter" "round""round"接合部の形状
SmoothTrue FalseFalseTrue: スプライン、False: 折線
SplineSteps数値スプラインの線分数
Stippleビットマップ塗りつぶしのビットマップ
Tags文字列そのアイテムにつけるタグ達
Width数値(ピクセル)1線の幅

Lineの属性

LineExample.jpg

LineのCapStyleとJoinStyle属性

Oval

Oval は楕円を描きます。Create$Ovalはその惰円の外接長方形の二つの対角頂点の座標を最初の4つのパラメータとします。

属性デフォルト効果
Fill無指定内部色
Outline"black"輪郭線の色
Stippleビットマップ塗りつぶしのビットマップ
Tags文字列そのアイテムにつけるタグ達
Width数値(ピクセル)1輪郭線の幅

Ovalの属性

Polygon

Polygon は閉じた他辺形を描きます。ただし、外形線はなく、全体が一体として扱われます。Create$Polygon} のパラメータは頂点の座標をa math image, ... と順に並べたものです。属性 Smooth が True のときは頂点はスプライン曲線で結ばれ、False のときは直線で結ばれます。 表に属性を掲げます。

属性デフォルト効果
Fill"black"全体色
SmoothTrue FalseFalseTrue: スプライン、False: 折線
SplineSteps数値スプラインの線分数
Stippleビットマップ塗りつぶしのビットマップ
Tags文字列そのアイテムにつけるタグ達

Polygonの属性

次の例は下図に成ります。

 w = Window[];
 c = Canvas[w, Width -> 600, Height -> 160];
 param := {x, y, x + 40, y - 40, 
   x + 80, y, x + 120, y + 40, 
   x + 160, y, x + 120, y - 40,
   x + 80, y, x + 40, y + 40};
 {x, y} = {20, 60};
 c[Create$Polygon] = {param, Smooth -> False};
 c[Create$Text] = {x + 80, y + 60,
   Text -> "Smooth -> False"};
 {x, y} = {200, 60};
 c[Create$Polygon] = {param, Smooth -> True};
 c[Create$Text] = {x + 80, y + 60,
   Text -> "Smooth -> True"};
 {x, y} = {380, 60};
 c[Create$Polygon] = {param, Smooth -> True,
   SplineSteps -> 3};
 c[Create$Text] = {x + 80, y + 60,
   Text -> "Smooth -> True"};
 c[Create$Text] = {x + 80, y + 76,
   Text -> "SplineSteps -> 3"};
Polygon.jpg

Polygonの例。Smooth -> True により、スプラインが用いられる。

Rectangle

Rectangle は傾きのない長方形です。 Create$Rectangleはその二つの対角頂点の座標をパラメータとします。

属性デフォルト効果
Fill無指定内部色
Outline"black"輪郭線の色
Stippleビットマップ塗りつぶしのビットマップ
Tags文字列そのアイテムにつけるタグ達
Width数値(ピクセル)1輪郭線の幅

Rectangleの属性

Text

Text は文字列を表示します。また Entry 部品のようにそれを編集することもできますが、その説明は省きます。Create$Textは位置を指定するひと組の座標をパラメータとします。また、その座標と Text との相対位置は属性 Anchor と Justify で指定します。Text の属性は表に掲げます。

属性デフォルト効果
Anchor"c" "n" "ne" "e" "se" "s" "sw" "w" "nw""c"座標との相対位置
Fill"black"文字の色
Fontフォントフォント
Justify"left" "right" "center""left"文字の揃え方
Stippleビットマップ塗りつぶしのビットマップ
Tags文字列そのアイテムにつけるタグ達
Text文字列""表示文字列

Textの属性

Window

Window はCanvasの上に他の任意のTkinterの部品を貼るのに用います。Create$Windowは貼り付ける部品の位置を指定するひと組の座標をパラメータとし、属性 Window で部品を指定します。例えば次のようにすると、図の様な結果が得られます。

 w = Window[];
 c = Canvas[w, Height -> 300, Width -> 400];
 $DisplayFunction = CanvasDrawer;
 Canvas$Widget = c;
 Plot[Sin[x], {x, -Pi, Pi}];
 b = Button[c, Text -> "Button on Canvas"];
 c[Create$Window] = {150, 100, Window -> b};
CanvasWindow.jpg

Canvasの中のWindowの例

私がこれまで試した限りでは、上に貼る Frame などを透明にすることはできないようです。

アイテムの製作

Canvas 上に製作されたアイテムに対しては後から様々な操作を及ぼすことができます。 以下の説明でcはあるCanvas部品を表わすものとします。

属性の変更および調査、ItemConfigure

タグの付加、AddTag

アイテムの移動、Move

位置の変更および調査、Coords

アイテムの消去、Delete

アイテムの表示面の重なりの移動

タグの解除、Dtag

タグの調査、GetTags

アイテムへのイヴェントの結合

Canvas の各アイテム、あるいはタグのつけられた各グループには Bindにより、それぞれ独立にイヴェントを結合することができます。 その方法は、例えば

 c = Canvas[ ... ];
 c[Create$Oval] = { ... , Tags -> "a"};
 Bind[c, "Button-1", Print["OK"], Tags -> "a"];

の様に Bind にオプション Tags-> (タグまたはアイテム番号、あるいはそれらのリスト) を加えるだけで、あとは通常の部品に対する結合 (Bind参照) と全く同様です。 また、変数 $Eventにイヴェントを発生したアイテムの番号あるいはタグが返されます。

プロット関数で製作したグラフでのアイテム製作

Canvas$IDによるアイテム番号の記録

ListPlotや Plotなどのプロット関数も Canvas のアイテムの組み合わせでグラフを表現します。 したがって、それらのアイテム番号が知られれば、個々のアイテムに対して上記の各種の操作を加えることができます。ListPlot が製作したアイテムの番号は、オプション Tags-> True により、その都度シンボル Canvas$ID に記録されるようになっています。例えば、

 w = Window[];
 c = Canvas[w, Width -> 600, Height -> 400];
 $DisplayFunction = CanvasDrawer;
 Canvas$Widget = c;

 data = {{1, 2, 0.5}, {2, 3, 2},
   {3, 5, 0.5}, {4, 2, 0.5}, {5, -2, 0.5}};
 ListPlot[data, Tags -> True,
   Plot -> True, PlotJoined -> True, 
   PointSize -> 2];
 Print[Canvas$ID];

と 5点のエラーバー付のデータを図のようにプロットしたとします。

idplot.jpg

ListPlot でプロットしたグラフのアイテム番号。Tags -> Trueにより、Canvas$IDにアイテム番号が記録されます。この場合、グラフの線には 番号 17、データ点のマーカには番号 18-22、エラーバーには番号 23-27 が割り当てられます。Canvas$IDの値は {{17, 27}}になります。(図上の番号は説明のためのもので、実際には表示されません。)

 {{開始1, 終了1}, {開始2, 終了2}, ...}

という形式で表わされています。それぞれの要素リストは描かれるグラフィックス原子に対応します。この場合 16 以前のアイテム番号には座標軸や目盛などアイテムが割り当てられていますが、それらの数はグラフの条件に左右されるので、どれが何であるとは簡単には言えません。Canvas$ID の返すものは常にデータ、あるいは直接 Epilog などで書き込みを支持されたグラフィックス原子に対応するアイテムの番号だけです。また、アイテムは、グラフの線、マーカ、エラーバーの順に並び、アイテム番号はデータの順に並びます。エラーバーは両方向にあっても常にひとつのアイテムです。したがってアイテム番号とデータ点の対応は一意的です。PlotRange により表示されるデータ点が制限される場合でも、アイテムは必ず製作され、アイテム番号も付加されます。ただし、グラフの線は破線などの場合にはひとつのアイテムにはなりません。

Showにより複数のプロットを同時に表示するような場合にも Canvas$ID にはプロット毎、あるいはグラフィックス原子毎に アイテム番号が {開始, 終了}というリストで記録されます。

Canvas$ID の値は ListPlot などのオプション Initializeが True のとき (デフォルト) にリセットされます。そうでない時にはそれまでの Canvas$ID に次々に追加されていきます。

Bindによるアイテムへのイヴェントの結合

以上の方法で各アイテムのアイテム番号がわかりましたから、今度はそれを使って各アイテムにイヴェントを結び付けてみましょう。これは基本的にはアイテムへのイベントの結合で説明したことの応用です。まず、上の例に加えて、

 ld = Length[data];
 markers = Canvas$ID[[1, 1]] + Range[ld];
 Bind[c, "<Button-1>", cmd, Tags -> markers];

とすると、markers にはマーカ達のアイテム番号がリストになって入ります。この場合は {18, 19, 20, 21, 22}になります。次に、Bind で Tags -> markers と指定することにより、各マーカはイヴェント "<Button-1>" (マウスボタン1 の押し下げ) が発生する度に式 cmd を評価実行することに割り当てられました。そこで、例えば

  (switch[#] = True)& /@ markers;                    (ア)
  markcolor[True] = "green";                         (イ)
  markcolor[False] = "red";                          (ウ)
  errorbarcolor[True] = "black";                     (エ)
  errorbarcolor[False] = "gray";                     (オ)
  cmd := Module[{id = ToExpression[Tag /. $Event]},  (カ)
    switch[id] =  switch[id];                        (キ)
    c[ItConfigure] = {id,
      Fill -> markcolor[switch[id]]};                (ク)
    c[ItConfigure] = {id + ld,
      Fill -> errorbarcolor[switch[id]]}];           (ケ)

とすると、各マーカをクリックする度に図の様にそのマーカとエラーバーの色をトグルすることができます。

Toggle.jpg

マーカをクリックするとそのマーカとエラーバーの色がトグルする。

ここでまず、(ア)はシンボル switch をマーカの状態を保持する関数として定義しています。(イ) から (オ) はそれぞれの状態に対応する色の定義です。(カ) から (ケ) がシンボル cmd の定義ですが、まず (カ) では局所シンボル id にシンボル Tag の $Eventを用いた置換により、クリックされたアイテムのアイテム番号を取り出しています。$Event はこの場合

{(Widget:>c),(Tag->"20"),(Type->"<Button>"),(X->291),(Y->24),(XRoot->693),
 (YRoot->542),(Height->0),(Width->0),(Char->"??"),(KeySym->"??"),
 (SendEvent->0),(KeyCode->),(State->0),(KeySymNum->),(Time->6784003)}

の様な規則のリストです。$Event は大域的なシンボルですが、イヴェントが発生し結合されたコマンドが呼ばれる度に値が局所的に設定されます(ローカルシンボルの節参照)。$Event に含まれるシンボルについてはEvent Symbolの表を参照してください。

(キ)は switch のトグルです。(ク)、(ケ) は番号 id のマーカ及び番号 id + ld のエラーバーの色を設定し直しています。こうして、アイテムとイヴェントを結合する基本的な動作は確認されました。


トップ   差分 バックアップ リロード   一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2008-05-15 (木) 22:52:36