この例で定義した MoveObjectInteractor クラスを使用すると、マウスでオブジェクトを移動したり、マウス・ボタンを放す場所までオブジェクトを移動したりできます。この例の完全コードは、インストール済みの製品の codefragments/interactors/moveobjinter/src/MoveObjectInteractor.java の MoveObjectInteractor.java にあります。詳細については、
<installdir>
/jviews-framework89/codefragments/interactors/moveobjinter/index.html を参照してください。
public class MoveObjectInteractor extends IlvObjectInteractor { private IlvRect mrect; private float dx, dy; private boolean dragging = false; /** Creates an moveObjectInteractor. */ public MoveObjectInteractor() { super(); } ... }
MoveObjectInteractor
は IlvObjectInteractor
クラスの機能を拡張し、次の属性を定義します。- 属性
mrect
は、グラフィック・オブジェクトの将来の矩形領域を指定します。このデータはオブジェクトをドラッグするたびに更新されます。 dx
属性とdy
属性は、元のクリック・ポイントからの移動とグラフィック・オブジェクトの現在の左上隅ポイントを表します。- ブール型値
dragging
は、オブジェクトのドラッグを開始すると、true
に設定されます。
イベントは、次のように
processEvent
メソッドで処理されます。protected boolean processEvent(IlvGraphic obj, AWTEvent event, IlvObjectInteractorContext context) { switch (event.getID()) { case MouseEvent.MOUSE_PRESSED: return processButtonDown(obj, (MouseEvent)event, context); case MouseEvent.MOUSE_DRAGGED: return processButtonDragged(obj, (MouseEvent)event, context); case MouseEvent.MOUSE_RELEASED: return processButtonUp(obj, (MouseEvent)event, context); default: return false; } }
processEvent
メソッドは、そのタイプにより 3 つの異なるメソッドにイベントをディスパッチします。processEvent
メソッドは、パラメーターとしてグラフィック・オブジェクト、イベント、コンテキストを取ります。コンテキスト IlvObjectInteractorContext は、オブジェクト・インタラクターを使用できるようにするためにクラスが実装する必要のあるインターフェースです。クラス IlvManager は、それを処理し、コンテキスト・オブジェクトをオブジェクト・インタラクターに渡します。コンテキストで、トランスフォーマーの取得、マウス・カーソルの変更などができます。次の
processButtonDown
メソッドでは、クリック・ポイントとグラフィック・オブジェクトの現在の左上隅ポイント間の距離は、属性 dx
と dy
に格納されます。位置はビューの座標系に保存されます。グラフィック・オブジェクトの左上隅はオブジェクトの矩形領域から抽出され、boundingBox
メソッドで計算されます。次に invalidateGhost
メソッドを呼び出します。このメソッドではインタラクター・コンテキストを要求し、mrect
に保存された現在の矩形領域に対応する領域を再描画します。public boolean processButtonDown(IlvGraphic obj, MouseEvent event, IlvObjectInteractorContext context) { if ((event.getModifiers() & InputEvent.BUTTON2_MASK) != 0 || (event.getModifiers() & InputEvent.BUTTON3_MASK) != 0) return true ; if (dragging) return true ; dragging = true; IlvPoint p = new IlvPoint(event.getX(), event.getY()); mrect = obj.boundingBox(context.getTransformer()); dx = p.x - mrect.x; dy = p.y - mrect.y; invalidateGhost(obj, context); return true; }
invalidateGhost
メソッドは次のように実装されます。private void invalidateGhost(IlvGraphic obj, IlvObjectInteractorContext context) { if (obj == null || context == null) return; if (mrect == null || mrect.width == 0 || mrect.height == 0) return; IlvRect invalidRegion = new IlvRect(mrect); context.repaint(invalidRegion); }
ゴーストの描画および消去の原則は次のとおりです。ゴーストの描画が行われるのは描画システムによって要求される場合のみであり、インタラクターはコンテキストの領域 (位置変更前後のゴーストの範囲) を無効にします。基本クラス
IlvObjectInteractor
に定義されたメソッド handleExpose
は、ビューが再描画されたときだけに呼び出されます。基本クラスで実装しても何も実行しないこのメソッドは、次のようにオーバーライドされます。public void handleExpose(IlvGraphic obj, Graphics g, IlvObjectInteractorContext context) { drawGhost(obj, g, context); }
ゴーストの実際の描画は、次の
drawGhost
メソッドで行われます。protected void drawGhost(IlvGraphic obj, Graphics g, IlvObjectInteractorContext context) { if (mrect != null) { g.setColor(context.getDefaultGhostColor()); g.setXORMode(context.getDefaultXORColor()); IlvTransformer t = context.getTransformer(); IlvRect r = obj.boundingBox(t); IlvTransformer t1 = new IlvTransformer(new IlvPoint(mrect.x - r.x, mrect.y -r.y)); t.compose(t1); obj.draw(g, t); } }
引数として渡された
Graphics
オブジェクトは、デフォルトの XOR 色とコンテキストに定義されたゴーストの色を使用して XOR モードに設定されます。次に、トランスフォーマーが計算され、mrect
が指定する目的の場所にオブジェクトが描画されます。オブジェクトは移動させないで、別の場所で描画されます。mrect
が null
の場合は、メソッドは何も行いません。これで、インタラクション終了後に drawGhost
メソッドが呼び出されたときに、ゴーストが描画されないようにできます。マウス・ドラッグされたイベントは、以下のように処理されます。
protected boolean processButtonDragged(IlvGraphic obj, MouseEvent event, IlvObjectInteractorContext context) { if (!dragging || mrect == null) return false; IlvPoint p = new IlvPoint(event.getX(), event.getY()); invalidateGhost(obj, context); mrect.move(p.x - dx, p.y - dy); IlvTransformer t = context.getTransformer(); if (t != null) t.inverse(mrect); context.ensureVisible(p); t = context.getTransformer(); if (t != null) t.apply(mrect); invalidateGhost(obj, context); return true; }
まず、
invalidateGhost
を呼び出して、現行ゴーストを無効にします。新規の目的の場所が、元の位置と一緒に移動してマウスの位置に移動します。mrect.move(p.x - dx, p.y - dy);
次に
ensureVisible
がコンテキストで呼び出されます。現在のドラッグ先のポイントがビューの可視領域外の場合は、マネージャーのビューをスクロールしてドラッグ先ポイントが可視になるようにします。この操作を行うと、mrect
の値がビューの座標系に保存されるため、ビューのトランスフォーマーが変わることがあります。ensureVisible
を呼び出す前に、次のように mrect
の値をマネージャー座標系に変換します。IlvTransformer t = context.getTransformer(); if (t != null) t.inverse(mrect);
ensureVisible
を呼び出した後、次のように mrect
の値を変換してビューの座標系に戻します。t = context.getTransformer(); if (t != null) t.apply(mrect);
グラフィック・オブジェクトの実際の移動は、マウス・ボタンを放したときに行われます。マウスを放して行うイベントは、次のように処理します。
protected boolean processButtonUp(IlvGraphic obj, MouseEvent event, IlvObjectInteractorContext context) { if (!dragging || mrect == null) return true; dragging = false; invalidateGhost(obj, context); doMove(obj, context); mrect = null; return true; }
まず、
invalidateGhost
メソッドを呼び出して、ゴーストを無効にします。次に、doMove
メソッドを呼び出します。このメソッドは、mrect
の最終座標に基づいてグラフィック・オブジェクトの位置を更新します。オブジェクトを移動後、mrect
を null
に設定し、ゴーストをそれ以上描画できないようにします。メソッド
doMove
の実装は次のとおりです。void doMove(IlvGraphic graphic, IlvObjectInteractorContext context) { if (mrect == null) return; IlvTransformer t = context.getTransformer(); if (t != null) t.inverse(mrect); graphic.getGraphicBag().moveObject(graphic, mrect.x, mrect.y, true); }
mrect
の値は、次のようにマネージャーの座標系に変換されます。IlvTransformer t = context.getTransformer(); if (t != null) t.inverse(mrect);
グラフィック・オブジェクトのメソッドを直接呼び出して、管理済みグラフィック・オブジェクトの位置または形状を直接変更することのないようにしてください (より正確にいえば、バウンディング・ボックスを変更しないでください)。そのような変更は関数で行う必要があります。この場合は
moveObject
で、マネージャーに適用され、必要な予防措置をすべて実行します。詳細については、「オブジェクトのジオメトリー・プロパティーの変更」を参照してください。