« 時計をつくる7 | トップページ | 時計をつくる9 »

2010年10月 8日 (金)

時計をつくる8

今回は実装予定だった最後の機能、「マウスから逃げる」を追加してみます。

説明すると、時計の表示でその下にあるウィンドウの内容が見えなくて困ることが時折あります。こういった場合、ウィンドウの内容を見るために一時的に退 いてくれると便利です。Through Clockのオプションではマウスを時計の上に置くことで時計がマウスカーソルから逃げるように遠のいてくれる機能があります。観終わったあと、マウスを戻すと時計も元の位置に戻ります。この機能 が「マウスから逃げる」機能です。(下図はイメージ)

Escape_from_mouse

こんなカンジの機能を実装するには、マウスが時計の上に重なったか調べることと離れたことを確認できれば実現できそうです。
早速調べてみるとWx::MouseEventにenteringというズバリなメソッドを発見。evt_enter_windowで重なったときに処理をセットすることができました。重なったときに座標を少し移動するように処理を追加。

マウスが離れたときはleaving。元の位置に戻します。なんか簡単だな、と思っていたらやはり罠が。重なったときに時計が移動するので、その瞬間にleavingのイベントが発生。leavingの処理で元の位置に戻るので今度は重なってenteringイベントが発生。これがループして時計が2つあるような残像になってしまいました。まあよく考えれば当たり前でした。

ということなのでenteringイベントの処理はよいとして、時計の移動後にまだマウスが元の位置にいる場合は戻さない、マウスが完全に遠のいた場合に時計を元の位置に戻すといった処理にしないとダメなようです。

これをどう実現するか。Wx::MouseEventはどうやら自分のウィンドウ内でしか発生しないようなのでマウスがウィンドウ外にある場合のマウスの座標が取得できません。

早速リファレンスをチェック。しかしウィンドウ外にあるのケースは探しても見つかりません。仕方が無いので自分でイベント生成したりTimerEventからなんとか取れないだろうかと試行してみましたが上手くいきません。

一日中試行錯誤して、あゝもう無理 と諦めた瞬間、ひとすじの光が。何気なくChangeLog を眺めていると

- Add global Wx functions for finding current mouse position (AF)

キャーッ!!まさに欲しかったものズバリだああああああああアァッ!!!
でもこれだけだと詳細がわからない。こうなったらgrepで検索だ!ということで一行だけこのファンクションが使用されている場所を発見。それがWx::get_mouse_position。
wxpythonでは既に実装されていてドキュメントもちゃんとあるようだ。

ここまでわかればあとはテスト用のコードを書いてみて試すだけ。実行するとWx::Pointでマウスの位置を返してくるようだ。OK。あとはこんなカンジに実装した。

  1.   # Mouse on Frame
  2.   def on_Entering(event)
  3.     mouse_position = event.get_position # Mouse position with Frame centered
  4.     position       = get_position       # Frame position with screen centered
  5.     client_area    = get_client_rect    # Frame position with Frame centered
  6.  
  7.     # Store current Frame position
  8.     @prev_position.push(position)
  9.  
  10.     # Delta X,Y
  11.     dx = @rtc_config.escape.x
  12.     dy = @rtc_config.escape.y
  13.     # Center XY of Frame
  14.     centre_x = client_area.x + client_area.width  / 2
  15.     centre_y = client_area.y + client_area.height / 2
  16.  
  17.     if (centre_x - mouse_position.x) < 0
  18.       dx = -dx
  19.     end
  20.     if (centre_y - mouse_position.y) < 0
  21.       dy = -dy
  22.     end
  23.     move(position.x + dx, position.y + dy)
  24.   end
  25.  
  26.   # If mouse not on the Frame, Frame will back to old position
  27.   def check_mouse_position
  28.     mouse_position = Wx::get_mouse_position # Screen centered position
  29.     client_area = get_screen_rect           # Screen centered position
  30.     # client_area = get_rect
  31.  
  32.     unless client_area.contains(mouse_position)
  33.       position = @prev_position.shift
  34.       move(position) if position
  35.       @prev_position = []
  36.     end
  37.   end
  38.  

check_mouse_positionはTimerで定期的に座標をチェックして重なっていないようであれば元の位置に戻すようにしてみました。設定ファイルに逃げる際の移動距離を追加。ダイアログでも設定を追加した。

1

これで一先ず完成としておこう。

|

« 時計をつくる7 | トップページ | 時計をつくる9 »

時計をつくる」カテゴリの記事

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック

この記事のトラックバックURL:
http://app.f.cocolog-nifty.com/t/trackback/1201593/37124577

この記事へのトラックバック一覧です: 時計をつくる8:

« 時計をつくる7 | トップページ | 時計をつくる9 »