- PR -

あるコンポーネントのマウスイベントを外し、別のコンポーネントにマウスイベントを発生させる方法

1
投稿者投稿内容
らびとら
会議室デビュー日: 2006/02/22
投稿数: 3
投稿日時: 2006-02-22 23:56
質問、初めてになります。
よろしくお願いします。

あるコンポーネントをマウスでドラッグし、mouseDragged イベントが発生したら、
別のコンポーネントに mouseDragged イベント(マウスイベント)を発生させ、
元のコンポーネントからマウスイベントを外したいと思っています。
(この際、マウスはドラッグしたままの状態です)
Win32ですと、WM_MOUSEMOVE メッセージ中に ReleaseCapture() 関数でウインドウの
マウスキャプチャーを外し、SetCapture() 関数で別のウインドウに
マウスキャプチャーを移すことが可能ですが、
Java でそれと同じように実行する方法がどうしても判りません。

どなたかご教授をよろしくお願いします。


例えば…
======================================================================
public class A extends Component implements MouseListener, MouseMotionListener
{
  public A()
  {
    addMouseListener(this);
    addMouseMotionListener(this);
  }

  public void mouseDragged( MouseEvent e )
  {
    // ここに入ったら、この A のマウスイベントを外し、
    // その後は B にマウスイベントを移し、
    // A にはマウスイベントは発生しない。
    System.out.println("A");

    // この B にマウスイベントを移したい。
    B b = new B();

    getParent().add(b);
  }
}

public class B extends Component implements MouseListener, MouseMotionListener
{
  public B()
  {
    addMouseListener(this);
    addMouseMotionListener(this);
  }

  public void mouseDragged( MouseEvent e )
  {
    // A からマウスイベントが外されて、
    // 他の mouseReleased 等、全てのマウスイベントが B に
    // 発生するようにしたい。
    System.out.println("B");
  }
}

[ メッセージ編集済み 編集者: らびとら 編集日時 2006-02-22 23:59 ]
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2006-02-23 02:47
要件に合っているかはわかりませんが、それぞれのコンポーネントで MouseListener を実装するのではなく、同じ MouseListner 実装済みクラスのインスタンスを共有するのはいかがでしょう。
nekoyama
ベテラン
会議室デビュー日: 2005/03/12
投稿数: 71
投稿日時: 2006-02-23 03:41
インギさんの方法で要件を満たすのならば、その方が実装が楽だと思いますが、
「マウスイベントを外す」がMouseListnerを外すという意味でないと解釈したうえで、
以下の方法でも多分、実現できます。

Componentを継承しているクラスAのprocessMouseEvent(MouseEvent),protected void processMouseMotionEvent(MouseEvent)をオーバーライドして、MouseEventをフックして、Component#dispatchEvent(AWTEvent)でクラスBにイベントを伝播後、MouseEvent#consume()で「マウスイベントを外す」。

dispatchEvent(AWTEvent)使用時は、コンポーネント間のMouseEventの座標変換も忘れずに。





らびとら
会議室デビュー日: 2006/02/22
投稿数: 3
投稿日時: 2006-02-23 09:09
インギさん、未記入さん、早速のご返事ありがとうございます。

少し説明が足りなかったので追加で説明しますと、
アイコンのドラッグ&ドロップと似たシステムを作ろうと思っています。
実際にはアイコンではありませんが、この点は不要かと思うので省きます。

ウインドウズのアイコンで例えると(基本的にやりたい事はこれと同じです…)、
デスクトップ上(エクスプローラ)に並んだアイコンをドラッグすると、
ドラッグ元のアイコンのゴースト(半透明のアイコン)が現れます。
そして、ドラッグ元のアイコンはその場に残ったままの状態で、
現れたゴーストのアイコンをドラッグしたままマウスで移動することができ、
ドロップするとドラッグ元のアイコンがマウスで指定した場所に移動し、ゴーストのアイコンが消えます。

この過程で『ドラッグ元のアイコン』には、
マウスを押してほんの少し移動するまではマウスイベントが発生しています。
ですが、ドロップ開始状態になり『ゴーストのアイコン』が現れると、
『ドラッグ元のアイコン』側のマウスイベントが解除され発生しない状態になり、
ドロップするまでの間、『ゴーストのアイコン』側にマウスイベントが発生し続けます。
つまり「マウスを移動している、マウスを放す」等のマウスイベントの発生元が完全に移った状態になります。
そしてドロップすると『ゴーストのアイコン』が消え、その場所に『ドラッグ元のアイコン』が移動します。
先の例では『ドラッグ元のアイコン』がクラスAで、
『ゴーストのアイコン』がクラスB(インスタンスb)となります。

このシステムを作るために、指定のコンポーネントの
マウスイベント(Win32ではマウスキャプチャーという名前)の
解除と設定を制御する方法を探っていました。


ひとまず未記入さんの方法で作成して目的のものが作成出来ました。
しかし、クラスAに送られ続けるマウスイベントをクラスBに送り続けるという方法のため、
少し思っていたイメージと異なり、力技のように感じました。
ですが、これでも可能なのでこのまま終了しても良いのですが、
もし僕のイメージ通り(このイメージが言葉足らずで説明不足になっているのかもしれませんが…)
の方法がありましたら、引き続きご教授をよろしくお願いします。


PS.
言葉の定義が曖昧でしたら申し訳ございません。
また「マウスイベントを外す」は MouseListner を Component#removeMouseListener() で外すという意味ではありません。
「マウスイベントを外す」とは、マウスイベントが「送られなくなる」という意味です。
再度、そのコンポーネントをクリック等すれば各種マウスイベントが発生するという事になります。
山本 裕介
ぬし
会議室デビュー日: 2003/05/22
投稿数: 2415
お住まい・勤務地: 恵比寿
投稿日時: 2006-02-23 09:53
DnDを実現するならそれに対応する API がありますので、そちらの方がすんなりいくかもしれません。
http://java.sun.com/j2se/1.4.2/docs/api/java/awt/dnd/package-frame.html
らびとら
会議室デビュー日: 2006/02/22
投稿数: 3
投稿日時: 2006-02-23 21:32
ドラッグ&ドロップ専用のAPIが存在したのですね。
インギさん、ありがとうございました。
目的からすると、こちらの方がシックリきます。
マウスイベントの設定と解除方法が分からずじまいなのが、
個人的には少し気がかりですが…(汗
ひとまず、これがあれば不要という事でお開きにします。

インギさん、未記入さん、大変助かりました。
ご教授ありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)