2012年8月29日水曜日

[ドリトル] ドリトルのマウス

ドリトルでマウスの現在座標は Screen オブジェクトに対する xPosition?yPoistion? で取得する。
mouseMoved のようなマウスが動いたときに発生するイベントのようなものはないので、基本的には タイマーやほかのオブジェクトのイベント実行時に、その時点でのマウス座標を取得するという形式で利用する。

// create axes
t1 = Turtle ! create.
t1 ! 1 linewidth (red) linecolor.
t1 ! penup -1000 -1000 moveto pendown.
xLine = t1 ! 1000 -1000 moveto makeFigure.
t1 ! penup -1000 -1000 moveto pendown.
yLine = t1 ! -1000 1000 moveto makeFigure. 
t1 ! hide.

// create value fields
txtField1 = TextField ! create.
txtField2 = TextField ! create.

timer1 = Timer ! create.
timer1 ! 0.01 interval 600 duration.

timer1 ! [
  txtField1 ! ( Screen ! xPosition? ) set.
  txtField2 ! ( Screen ! yPosition? ) set.
  xLine ! -1000 (Screen ! yPosition?) moveto.
  yLine ! (Screen ! xPosition?) -1000 moveto.
] execute.

一方でマウスクリックイベントはタートルや図形、各種 GUI オブジェクトが action イベントとして受け取る形式で取得する。
したがって一見何もないところでマウスクリックのイベントを拾うためには、背景に不可視(hide されていてはイベントが拾えないので白色など)の図形( Figure )を配置しておく必要がある。

// create background shape
t1 = Turtle ! create.
t1 ! (red) linecolor 2 linewidth.
t1 ! penup -1000 1000 moveto pendown.
background = t1 ! 2000 4 polygon makeFigure (white) paint.

t1 ! penup (blue) lineColor hide.
background:action = [
  t1 ! show penup (Screen!xPosition?) ((Screen!yPosition?) + 20) moveto.
  t1 ! pendown 20 circle makeFigure (blue) paint.
  t1 ! hide.
].

マウスが押された場所に円を配置する。任意の場所でマウスクリックイベントを拾うために、 (-1000, 1000) - (1000,-1000)へ一辺 2000 の正方形を配置し白く塗りつぶしてある。

polygon 命令は 右下(X軸はプラス方向、Y軸はマイナス方向)へ描画するので初期位置は(-1000, 1000)。
paint で塗りつぶさないと辺上でしか action イベントが発生しないので 白色で塗りつぶしてある。



この方法の問題点は、手前にオブジェクトが来てしまうと背景の Shape にクリックイベントが起きないこと。この例でも円が配置されてしまうと、その円上でクリックしても何も起きない。

考えられる解消策は2つ。
  • 背景を半透明にして手前に表示
  • 手前のオブジェクトで action を拾ったら背景オブジェクトの action を呼ぶ。
前者はたとえ半透明の白にしても後ろのオブジェクトがかすんでしまう。また、図形(Figure)には「手前に表示」という表示順序を制御する命令があるはずなのだが「そんな命令はない」とエラーになってしまうので実現できそうにない。

後者は必要な全オブジェクトでこれをしないといけないのでいろんなオブジェクトがあると相当面倒。
とりあえず今回のサンプルであればこんな感じで書ける。

// create background shape
t1 = Turtle ! create.
t1 ! (red) linecolor 2 linewidth.
t1 ! penup -1000 1000 moveto pendown.
background = t1 ! 2000 4 polygon makeFigure (white) paint.

//background ! 手前に表示.

t1 ! penup (blue) lineColor hide.
background:action = [  |; figure |
  t1 ! show penup (Screen!xPosition?) ((Screen!yPosition?) + 20) moveto.
  figure = t1 ! pendown 20 circle makeFigure (blue) paint.
  figure:action = [ background ! action ].
  t1 ! hide.
].

新たに描画した円上でクリックされた場合でも背景の action が実行されるので新たな円がクリックした場所に作成されるようになる。


0 件のコメント:

コメントを投稿