今日はShape等の形に合わせてマウスを動かす話です。
マウスを複雑な形に動かしたり、ドラッグさせるにはShapeを使うのが簡単です。
あと、わざわざ記事にしたのは
[Java]PathIterator を Point2D 配列へ変換する
というNI-Lab’.sさんの古い記事が検索トップであったのですが、これが微妙に間違っ てる ていたので訂正もかねて。
まずはこんな感じでマウスを動かす為の関数が用意されていることにしておきます。
Robot rob; { try { rob = new Robot(); } catch (AWTException e) { e.printStackTrace(); System.exit(1); } rob.setAutoDelay(30); } //毎回(int)xと書くのがめんどうなのでdouble型 public void move(double x,double y){ rob.mouseMove((int)x, (int)y); } public void press(double x,double y){ move(x,y); press(); } public void press(){ rob.mousePress(InputEvent.BUTTON1_DOWN_MASK); } public void release(double x,double y){ move(x,y); release(); } public void release(){ rob.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); }
ついでに、こんな内部クラスを用意しておきました。
class MousePoint{ double x,y; boolean move=true;//press,release時に移動するかどうか。 int type;//0:move 1:press 2:release void doWork(){ switch(type){ case 0://move move(x,y); break; case 1://press if(move)press(x,y); else press(); break; case 2://release if(move)release(x,y); else release(); break; } } }
これで準備おk。
では、実際にShapeを使ってマウスをドラッグしてみましょう。
ここではLINETOとCLOSEというセグメントが出たときにドラッグするようにしたよ。
public void dragShape(Shape s) { //ShapeからPathIteratorを取得 PathIterator path= s.getPathIterator(null); //FlatteningPathIteratorでペジェ曲線を直線の集まりに変換。 FlatteningPathIterator p = new FlatteningPathIterator(path, 0.1); //マウスポイントを保持するリスト ArrayList<MousePoint> list = new ArrayList<MousePoint>(); //PathIteratorから点を読み込むのに使います。定石です。 double[] coords = new double[6]; int type; MousePoint beforepoint=null, lastmoveto=null;//SEG_MOVETOの最も新しい点は必ず一つ保存しておきます。 while(!p.isDone()){ type = p.currentSegment(coords); switch(type){ case PathIterator.SEG_MOVETO: beforepoint =lastmoveto= new MousePoint(); beforepoint.x =coords[0]; beforepoint.y =coords[1]; beforepoint.type = 0;//move list.add(beforepoint); break; case PathIterator.SEG_CLOSE: beforepoint.type =(beforepoint.type==2)?0: 1;//releaseならmoveにそうでなければpressに beforepoint = new MousePoint(); beforepoint.x =lastmoveto.x;//最後にmovetoした点に移動する。 beforepoint.y =lastmoveto.y; beforepoint.type = 2;//release list.add(beforepoint); break; case PathIterator.SEG_LINETO: beforepoint.type =(beforepoint.type==2)?0: 1;//releaseならmoveにそうでなければpressに beforepoint = new MousePoint(); beforepoint.x =coords[0]; beforepoint.y =coords[1]; beforepoint.type = 2;//release list.add(beforepoint); break; } p.next(); } ///////////////ここまででPathIteratorをマウス座標に変換完了 //実際に動かす。 for(MousePoint m:list)m.doWork(); }
問題となるのはセグメントCLOSEの時に最後のMOVETOセグメントの座標へ移動すると言うこと。これを忘れないようにしましょう。
実際にこんな感じのソースで動きをsaiに描画させて試してみましょう。
//saiにフォーカスを合わせる為にクリックしておきます。 move(400,400); press(); release(); ////////////////////////////////////////////////// //閉じた円弧のShapeを作成 Shape r = new Arc2D.Double(600, 200, 300, 300, 0, 230, Arc2D.CHORD); dragShape(r);