Java Drawing DrawTop

Language

JP  US  UK

 

図形の作成

 H. Jyounishi, Tokyo Japan
 

Frame (Index), No frame                 version:0.3(latest)  

要旨:ユーザが図形作成のために行うマウスの操作と動きを、図形要素(ShapeElement)に送って図形データを作成する。どの図形要素を作成するかは、マウス操作の前にツールバーのボタンを押して指定する。押されたボタンの番号は、commandId(整数)で渡される。画面への描画はDrawPanelからpaintメソッドを呼んで行う。

このページで説明するクラス: CreateShapeLS, DiscreteAngledLine


1. 概要
1.1 制御フロー概略
ユーザが図形作成のために行うマウスの操作と動きを、 図形要素(ShapeElement)に送って図形データを作成する。 どの図形要素を作成するかは、マウス操作の前にツールバーのボタンを押して指定する。 押されたボタンの番号は、commandId(整数)で渡される。 画面への描画はDrawPanelからpaintメソッドを呼んで行う。
See 詳細=> 図形作成の制御フロー


ツールバー上の図形作成ボタン


1.2 操作方法
=> 操作説明書 図形の作成

(1)閉図形(Rectangle, RoundRectangle, Ellipseなど)
メニューボタンを押して作画する図形を選択し、マウスで作画領域をドラッグする。ドラッグした矩形領域にフィットする閉図形が作成される。マウスドラッグではなくてクリックした場合、クリック点にデフォールトの小さな図形を作成する。


図1. 閉図形の作成

点線の矩形がドラッグ領域、矢印はドラッグ方向、楕円が作成された図形。



(2)直線(Line, 矢印つきLine)
メニューボタンを押して作画する直線(矢印なし/あり)を選び、マウスで画面をドラッグ。 ドラッグの始点と終点を結ぶ直線を作成する。
マウスドラッグではなくてクリックした場合、クリック点にデフォールトの小さな斜め線を作成する。


図2.直線の作成


(3)折れ線、三次曲線

折れ線(三次曲線)作成のメニューボタンを押し、 ①マウスで画面をクリックして最初の節点を決める、 ②マウスを動かしてひとつ前の節点との間にできる線分(曲線)を見ながら、クリックして次の節点を決定。 ①②を繰り返して折れ線(三次曲線)を作成する。マウスをダブルクリック/右ボタンクリックすると最後の節点を確定し終了。

図3の矢印は形が整っていないので使える代物ではないが、 後で説明する図形変更機能(Modify Shape)を使えば簡単に整形することができる。

図3.折れ線、三次曲線の作成


(4)部品ライブラリに登録されている図形

部品ライブラリの部品を選択し、画面をドラッグするとドラッグ領域にフィットする部品の図形が作成される。
マウスドラッグではなくてクリックした場合、クリック点にデフォールトの小さな部品図形を作成する。

=> 操作説明書ライブラリ図形


------------------------------------------
: Ctrl/Shiftキーの使い方
-------------------------------------------

Shift Key/Ctrl Keyを押しながらマウスをドラッグすると、

∙ 閉図形作成の場合は、正方形領域に図形を作成する。

∙ 直線、折れ線の場合には、線分を水平線、垂直線、45度線のいずれかに近い線分になる。

図4. Shift Key/Ctrl Keyを押しながら作成した図形


-----------------------------------------------------
: Connector enable オプション
------------------------------------------------------

∙ "connector enable" オプション (デフォールトはtrue)

このオプションがtrueで図形作成ボタンを押した後に、マウスを図形の境界に近づけると接続点候補点マークが表示される (図(a))。 このマークが表示されている間にマウスボタンを押して、マウスをドラッグし他の図形に近づけると その図形境界上に接続点マークが表示されマウスボタンを離すと、2つの図形を接続する直線を作成できる(図(b))。 この操作は折れ線に対しても同様に実行できる(図(c))。
2つの図形との接続を確認するためには、選択図形 の境界上でマウスボタンを押すと赤いマークが表示される。 このマークは接続点マークで選択図形が移動/リサイズされている間表示される(図(d))。


図 (a)


図 (b)


図 (c)


図 (d)

図 5. "connector enable" オプションと接続点マーク

2. CreateShapeLS(LS: Listener) 戻る=>page top
2.1 概要

項目

説明

CreateShapeLSの機能

図形作成のためのマウスの動作を図形要素(ShapeElement)に送る。 実際に図形データを作成するのは図形要素である。

閉図形または直線の場合

マウスドラッグでは、CreateShapeLSのメソッドが次のように呼び出される。

mousePressed -> mouseDragged繰り返し -> mouseReleased

mousePressedで初期設定、mouseDraggedの繰り返しで図形作成、mouseReleasedで後処理を行う。
図形作成はmouseDraggedから図形要素の createメソッドを呼んで行う。

折れ線、三次曲線の場合

mouseClickedでひとつの節点を確定する。 その後のマウスの動きをmouseMovedで受け取り、 ひとつ前に確定した節点とマウスの現在点を結ぶ線分または曲線セグメントを発生させ表示する。 ダブルクリックまたは右ボタンクリックで最後の節点を確定して終了。
マウスの現在点を未確定の節点として図形を作成して表示するため、 mouseMovedから図形要素のcreateメソッドを呼んで図形を作成する。

部品ライブラリを使う場合

閉図形の場合と同様にマウスドラッグで位置とサイズを指定する。



図形作成の制御フロー
CreateShapeLSが呼ばれるときの制御フローを閉図形作成の場合を例にとって説明する。

処理ステップ

説明

Step1. 起動

∙ 図形作成のボタンを押す

Step2. コマンド発行

∙ ボタンのアクション処理(ButtonOfToggleAction)で コマンド列を作成してコマンドディスパッチャーExecCommandを呼ぶ。

Step3. コマンド分岐(dispatch)

∙ ExecCommand でコマンド分岐。

CreateShapeLSオブジェクトを作成して、このクラスのcreatingStartメソッドを呼ぶ。

Step4. マウスリスナー設定、前処理

∙ creatingStartでCreateShapeLSをListenerPanelにセット。

∙ 図形選択リスナーSelectionLSを一時停止(動作させて置くと不要な選択処理を行ってしまう)。

∙ 図形作成コマンドの種類に応じ、図形要素 (RectangleElement, RoundRectangleElementなど)のオブジェクトを作成してマウスイベント待ちに入る。

Step5. 図形要素の作成

creatingStart メソッドでcommand idを参照して ShapeElement のサブクラスを作成し、 新しいShapeContainerオブジェクトにセットする。

Step6. 図形作成処理

∙ 画面上でマウスドラッグが始まると図形作成∙ 描画を開始。

∙ ドラッグ中はドラック領域の位置とサイズを図形要素に送り、 createメソッドで図形データの更新を繰り返す。
∙ 図形の描画はDrawPanelからpaintメソッドを呼んで行う。 図形作成中はmouseDragged, mouseMovedメソッドが呼ばれるたびに createメソッドを呼んで図形データを更新する。 この後にmouseDraggedメソッドでDrawPanelのrepaintメソッドを呼びDrawPanelを描画しなおす。

Step7. 後処理

マウスボタンが離されると図形作成終了。CreateShapeLS の creatingEndメソッドが呼ばれ終了処理を行う。

∙ CreateShapeLSをListenerPanelから削除して無効化。

SelectionLSを再起動。

∙ Undoの設定。
ExecCommandへ戻るコマンド列を作成。 このコマンドはCreateShapeLSの正常終了をExecCommandの報告する。



2.2 API
public class CreateShapeLS implements MouseListener, MouseMotionListener

フィールド

説明

shapeContainer

ShapeContainer shapeContainer

新規作成する図形のコンテナー。creatingStartでShapeContainerオブジェクトを新規に作成する。

shapeElement ShapeElement shapeElement
作成される ShapeElement オブジェクト。

commandId

int commandId:コマンドの種別を表す整数値。図形要素の種類を表す整数値と共用。

isLineFamily

boolean isLineFamily:直線/矢印付き直線の場合true。

isPolylineFamily

boolean isPolylineFamily:折れ線と三次曲線の時true。

isRectangleFamily

boolean isRectangleFamily:基本閉図形の時true。

これら3個のフラグは、判定分を見やすくするために使う。3種のファミリィは図形作成の方法が異なる。

isComponentFamily

boolean isComponentFamily:部品ライブラリの図形の時true。

これら3個のフラグは、判定分を見やすくするために使う。3種のファミリィは図形作成の方法が異なる。

startPoint

Point2D startPoint
ドラッグ開始点。但しctrl>0 (図4)、 または"connector enable"オプション (図5)がtrueの時は変更されることがある。

endPoint

Point2D endPoint
ドラッグ終了点。ドラッグ中はドラッグ現在点。但しctrl>0 (図4)、 または"connector enable"オプション (図5)がtrueの時は変更されることがある。

oldPoint

Point2D oldPoint
ひとつ前にmouseDraggedが呼ばれた時の点。endPointとoldPoint差が前回との差分。

pressedPoint

Point2D pressedPoint

マウスボタンが押されたときのマウス位置。この点は変更されない。

draggedPoint

Point2D draggedPoint

マウスドラッグのマウス位置。 mouseDraggedメソッドが呼ばれた時はいつも更新される。 但し他の理由では変更されない。

clicked

boolean clicked

mousePressed メソッドでfalseをセットし、 mouseClicked メソッドでtrueをセットする。

rightButtonPressed

boolean rightButtonPressed

マウス右ボタンが押されたときtrue。
See => Detection of the double-click or right button click

ctrl

int ctrl

ctrl=0: マウス左ボタンが押された。
ctrl=1: Shiftキーを押したままマウスボタンが押された。
ctrl=2: Ctrlキーを押したままマウスボタンが押された。
ctrl=3: Altキーを押したままマウスボタンが押された。

committedNodePoints

Point2D[] committedNodePoints

折れ線、区分的三次曲線の確定したセグメント接続点を格納する配列。

tentativeNodePoints

Point2D[] tentativeNodePoints

折れ線、区分的三次曲線の未確定のセグメント接続点を格納する配列。 図形作成中に図形を表示するために使う配列。実際に未確定なのは最後の点だけで残りは確定点。 マウスがクリックされたときに未確定点から確定点に変わる。


メソッド

説明

creatingStart

public void creatingStart(int commandId)

ExecComanndでCreateShapeLSオブジェクトを作成した後にこのメソッドを呼ぶ。

commandIdでCommandクラスで定義してあり、図形要素の種類を表す。

ShapeContainer(図形コンテナー)、 ShapeElement(図形要素)オブジェクトの作成

ここでは図形要素のオブジェクトだけ作り、図形データはmouseDraggedまたはmouseClickedメソッドで、 図形要素のcreateメソッドを呼んで作る。

作成したShapeContainerはContainerManagerContainerListに登録する。 登録した後は、DrawPanelのpaintメソッドで図形が画面に表示される。

∙ CreateShapeLSをマウスリスナーとして、 ListenerPanelに設定する。

これと同時にremoveMouseListenersを呼んで他のマウスリスナーを削除する。

(注) 部品ライブラリを使う場合

部品ライブラリダイアログから選択部品を取得し、部品のcloneを作成する。 cloneの図形要素、TextBox、PaintStyleオブジェクトをこのメソッドで作成したShapeContainerにセットする。
あとはマウスドラッグで位置とサイズが与えられるたびに、 リサイズメソッド(ShapeElement.moveResize)で ドラッグ領域に部品の図形をフィットさせる(this.mouseDraggedメソッド)。

creatingEnd

public void creatingEnd()
図形作成の後処理を行う。

閉図形と直線の場合はmouseReleasedメソッドがこのメソッドを呼び出す。 折れ線、三次曲線の場合は、mouseClickedでダブルクリックか、マウス右ボタンクリックを検出した時に、このメソッドを呼び出す。

∙ CreateShapeLSを、ListenerPanelから削除する。

これと同時にsetMouseListenersを呼んで他のマウスリスナーを再開する。

∙ ContainerManegerのundo設定機能を使って、図形作成処理のundo設定をする。

See=> ContainerManegerのundo設定機能

∙ 呼び出し元をCommand.callFromMouseListenerにしコマンドを作成する。

ExecCommand>のexecメソッドを呼び出し、ExecCommandにCraetShapeLSが正常終了したことを通知する。

abort

public void abort()

CreateShapeLSを中止する。たとえば直線作成メニューボタンを押して、 画面をドラッグして直線を作成せず、他のコマンドを指定した場合などにに呼ばれる。
コマンド分岐処理を行うExecCommandとこのクラスの mouseClickedメソッドから呼ばれる。

CreateShapeLSを、ListenerPanelから削除し、SelectionLS(図形選択クラス)を再開する。

=>; CreateShapeLSの深刻なエラー

mousePressed

public void mousePressed(MouseEvent e)

∙ ドラッグ領域の開始点をフィールド変数startPointに設定。

∙ マウスボタンを押した時にShiftキーを押しているとctrl=1、Ctrlキーを押しているとctrl=2、 マウス右ボタンを押すとctrl=3を設定。これは後で参照する。

mouseDragged

public void mouseDragged(MouseEvent e)

∙ ドラッグ領域の対角点を取得する。

isRectangleFamily=trueならばドラッグ領域(Rectangle2D)を、 図形要素のcreateメソッドに渡し図形を作成する。

isComponentFamily=trueならば、部品の図形をリサイズすればよいから、 ドラッグ領域を図形要素のmoveResizeメソッドに渡す。

isLineFamily=trueならばドラッグ開始点と現在点を 図形要素のcreateメソッドに渡し直線を作成する。

(注)ctrl=1/2の場合、直線ならは水平/45度/垂直線になるように、 閉図形ならば、縦横比が等しくなるようにドラッグ現在点を変更してcreateメソッドに渡す。

mouseReleased

public void mouseReleased(MouseEvent e)

∙ isRectangleFamily=trueまたはisLineFamily=trueならば、creatingEndメソッドを呼んで後処理。

mouseMoved

public void mouseMoved(MouseEvent e)

∙ 折れ線、三次曲線の最後のクリック点(確定点, committed points)と現在のマウス位置を結ぶ線分/曲線を作り図形要素のcreateメソッドを呼んで図形データを作成する。この段階ではマウスの現在点は仮の節点なので、マウスを動かすと図形が動く(下図)。

(注)ctrl=1/2の場合、水平/45度/垂直線になるようにドラッグ現在点を変更して createメソッドに渡す。

mouseClicked

public void mouseClicked(MouseEvent e)

∙ RectangleFamily、LineFamily、ComponentFamilyの場合、 デフォールトの小さな図形をクリック点に作成する。

∙ PolylineFamilyの場合

tentativeNodePoints の点列を committedNodePointsにコピーする。つまり確定点にする。
右ボタンクリックまたはダブルクリックならは creatingEndメソッドを呼んで、図形作成を終了。

See=> ダブルクリックまたは右ボタンクリックの検出

mouseEntered

public void mouseEntered(MouseEvent e)

∙ なにもしない

mouseExited

public void mouseExited(MouseEvent e)

∙ なにもしない

isDifferentPoint

private boolean isDifferentPoint(Point2D p1, Point2D p2)

∙ p1, p2が異なる点がどうか判定する。

getSpecialPoint

private Point2D getSpecialPoint(Point2D p0, Point2D p)

∙ 始点p0, 終点pを結ぶ線分を水平線、垂直線、45度線のいずれか近い線にする。

[戻り値] 終点pに変わる点を返す。

createNodePoint

private void createNodePoint(int ctrl, Point2D mousePT)

引数:

ctrl - ctrlと同じ。
mousePT - マウス位置。

処理:

committedNodePoints の全ての点を tentativeNodePointsにコピーし、 mouseMoved メソッドの新しい点を tentativeNodePointsに追加し、 shapeElementcreateメソッドを呼ぶ。


=> CreateShapeLSの深刻なエラー

エラーのケース

対応

折れ線、三次曲線作成にもかかわらず、マウスドラッグした場合。
マウスクリックが要求されている。

クリックのつもりがマウスが少し動いただけのケースがある。移動距離が小さい場合、 ドラッグの終了点に節点を作成する。
節点を作成せずにマウス動作待ちにしても特に問題は起きない。

閉図形、直線作成にもかかわらず、マウスクリックした場合

クリック点にデフォールトの小さな図形を作成する。

図形作成コマンドを選んだ後に、図形の移動、リサイズを実行しようとした場合。 マウスクドラッグが要求されている。

同上

図形作成コマンドを選んだ後に、右ボタンクリックした場合

同上

図形作成コマンドを選んだ後に、別のコマンドを選んだ場合

abortを呼ぶ。

この呼び出しはExecCommandのexecメソッドで行う。

(注)CreateShapeLSを起動するとExecCommandのフィールド変数 activeCreateShapeLSに CreateShapeLSオブジェクトを設定する。CreateShapeLSが正常終了すると、 this.creatingEndメソッドで終了コマンドを作成してExecCommandに戻り、 activeCreateShapeLSにnullにする。

例えばCreateShapeLを起動しただけで、他のメニューボタンを押した場合は、 activeCreateShapeLSをチェックすれば分かる。

この場合、execメソッドでコマンドを分岐させる前にactiveCreateShapeLSをチェックし、 nullでなければabortを呼ぶ。



: ダブルクリックまたは右ボタンクリックの検出
∙ ダブルクリックかどうかは、mouseClicked の引数で渡されるMouseEventのメソッド getClickCount()を使って判断できる。
∙ 右ボタンが押されたかどうかは、mouseClickedメソッド内のイベントには反映しないのでmouseClickedでは取得できない。
これはmousePressedメソッドでつぎのように取得する。

int ctrl=0;
if((key&InputEvent.SHIFT_DOWN_MASK)!=0) ctrl=1; //Shiftキーのチェック
if((key&InputEvent.CTRL_DOWN_MASK)!=0) ctrl=2; //Ctrlキーのチェック
if((key&InputEvent.BUTTON2_DOWN_MASK)!=0) ctrl=3; //右ボタンのチェック
if((key&InputEvent.BUTTON3_DOWN_MASK)!=0) ctrl=3; //右ボタンのチェック

mousePressedメソッドでフィールド変数ctrlフィールドに設定し、mouseClickedで参照する。
このためmouseClickedメソッドではmousePressed>メソッドで設定するctrlフィールドを参照する。


3. DiscreteAngledLineクラス 戻る=>page top
このクラスはマウスドラッグの方向を一定方向に制限するために使う。 例えばマウスドラッグで水平線/垂直線を作成する、図形を水平方向/垂直方向に移動するなど。

フィールド

説明

initAngle

double initAngle

x軸との角度 (初期値、度)

anglePitch

double anglePitch

角度のピッチ (度)

startPT

Point2D startPT

始点

direction

int direction

方向を表す整数値。方向が指定されていない時は-1。
例えばinitAngle=0, anglePitch=90のとき0≦direction≦3で、direction=0,2はx方向、direction=1,3はy方向を表す。

vec

Vector2D[] vec

コンストラクタで方向ベクトルを設定する。


メソッド

説明

コンストラクタ

public DiscreteAngledLine(double initAngle, double anglePitch, Point2D startPT)

引数を対応するフィールド変数に設定し、vecに方向ベクトルを設定する。 

getControlledPT
(static)

public Point2D getControlledPT(int ctrl, Point2D p)

通常は次の同名のstaticメソッドを使う。但し次のメソッドには欠点がある。pがp0の近くを動かすと、わずかなp動きで移動方向が変わってしまう点である。例えば最初pをx方向に動かした後にp0(始点)の近くに戻してくると、p0の近くでpの動きが突然y方向に制限されることがある。このような動作が不都合な処理ではこのメソッドを使う。
このメソッドは一旦pをx方向へ動かすと、ctrl=0として一度このメソッドを呼ばない限り、ずっとx方向に動かす。

引数:
ctrl - ctrl>0のときstartPTとpを結ぶ直線の方向を制限する。
p - 終点。

戻り値:

次の同名のメソッドと同じ値を返す。

getControlledPT
(static)

public static Point2D getControlledPT(double initAngle, double anglePitch, Point2D p0, Point2D p)

引数:
initAngle - x軸との角度 (度)。
anglePitch - 角度のピッチ (度)。
p0 - 始点。
p - 終点。

戻り値:

x軸との成す角度がinitAngle+anglePitch*n (n-0,1,2,...)なる直線から、 原点とpを結ぶ直線に最も近い直線を選び、その直線にpを投影した点を返す。
: initAngle=0, anglePitch=45ならば下図の点が戻る。



Copyright (c) 2009-2013
All other trademarks are property of their respective owners.