Java言語では配列のサイズをあとから変更することはできないようになって いるので,配列の大きさが足りなくなったら,新しくより大きな配列オブジェ クトを作成して(よく使われるのはこれまでのサイズの2倍),古い配列の内容 をコピーして使う方法である.
前のプログラムで,配列をどこまで使っているかを表すlineCountが増えるの は,マウスが離された時だけなので,以下のように置き換えてみることができ る.
public void mouseReleased(MouseEvent e){
// マウスカーソルの位置を得る
int mx=e.getX(),my=e.getY();
// デバッグ用の表示
System.out.println("mouseUp("+e+","+mx+","+my+")");
// 配列linesのlineCount番目の始点を変更
lines[lineCount].end_x=mx;
lines[lineCount].end_y=my;
// lineCountを増やす
lineCount++;
if(lineCount>=lines.length){
Line[] newLines=new Line[lines.length*2];
int i;
for(i=0;i< lines.length;i++)
newLines[i]=lines[i];
lines=newLines;
}
dragging=false;
// 再表示をおこなう
repaint();
}
なお,
int i;
for(i=0;i< lines.length;i++)
newLines[i]=lines[i];
のように,配列から配列へのコピーは, Systemクラスの arraycopyメソッドを使って,以下のように書くことができる.
System.arraycopy(lines,0,newLines,0,lines.length);
配列を管理するためにはどのような操作が必要かを考えて,クラスの設計を してみる.
class LineArray{
Line lines[];
int lineCount;
LineArray(){
lines=new Line[10];
lineCount=0;
}
int size(){
return lineCount;
}
void addElement(Line line){
lines[lineCount]=line;
lineCount++;
if(lineCount>=lines.length){
Line[] newLines=new Line[lines.length*2];
System.arraycopy(lines,0,newLines,0,lines.length);
lines=newLines;
}
}
Line elementAt(int index){
return lines[index];
}
}
これを使って,MouseDraw全体を書き直したのが以下のプログラムである.
// AWTを使うため,
import java.awt.*;
// イベント駆動関係のクラスを用いるため
import java.awt.event.*;
// 線分のクラスを定義する.
class Line{
// 始点,終点のX座標,Y座標を int で保持する.
public int start_x,start_y,end_x,end_y;
// Lineのコンストラクタ
public Line(int x1,int x2,int x3,int x4){
start_x=x1;
start_y=x2;
end_x=x3;
end_y=x4;
}
}
class LineArray{
Line lines[];
int lineCount;
LineArray(){
lines=new Line[10];
lineCount=0;
}
int size(){
return lineCount;
}
void addElement(Line line){
lines[lineCount]=line;
lineCount++;
if(lineCount>=lines.length){
Line[] newLines=new Line[lines.length*2];
System.arraycopy(lines,0,newLines,0,lines.length);
lines=newLines;
}
}
Line elementAt(int index){
return lines[index];
}
}
// インタフェースの実装では 「implements インタフェース名」と書く
// 複数書く場合は,カンマで区切る
class MouseDraw extends Frame implements KeyListener, MouseListener, MouseMotionListener{
// Lineの配列を保持するLineArrayクラスの変数 lineArrayの宣言
LineArray lineArray;
// マウスをドラッグ中かどうかを示す boolean型(真偽値)の変数draggingの宣言
boolean dragging;
// 表示する色を保持する変数
Color lineColor;
// コンストラクタの宣言
public MouseDraw(String title){
// 親クラス Frameのコンストラクタの宣言
super(title);
lineArray=new LineArray();
// ドラッグ中ではない
dragging=false;
// 線の色は黒に
lineColor=Color.black;
// GUI部品と,Event Listenerを関連づける
addKeyListener(this);
addMouseListener(this);
addMouseMotionListener(this);
}
public static void main(String args[]) {
// MouseDrawのインスタンスを作成 frameに代入
MouseDraw frame=new MouseDraw("MouseDraw");
// サイズを 600x400に設定
frame.setSize(600,400);
// 表示する.
frame.setVisible(true);
}
Image offScreenImage;
Graphics offScreenGraphics;
public void update(Graphics g){
if(offScreenImage==null){
offScreenImage=createImage(600,400); // オフスクリーンイメージを600x400のサイズで作成
offScreenGraphics=offScreenImage.getGraphics(); // オフスクリーンイメージに描画するための Graphics オブジェクト
}
paint(offScreenGraphics); // 次の画面のイメージを作る.
g.drawImage(offScreenImage,0,0,this); // イメージを本物のスクリーンに書き込む
}
// offScreenImageの書き直しをする際に呼ばれる
public void paint(Graphics g){
int i;
// 白で(0,0)-(600,400)を塗り潰す
g.setColor(Color.white);
g.fillRect(0,0,600,400);
// 色を設定
g.setColor(lineColor);
int size=lineArray.size();
if(dragging) size--;
for(i=0;i< size;i++){
Line l=lineArray.elementAt(i);
g.drawLine(l.start_x,l.start_y,l.end_x,l.end_y);
}
// マウスをドラッグ中の時は
if(dragging){
// 赤い色で
g.setColor(Color.red);
// lines[lineCount] を描画する.
Line l=lineArray.elementAt(i);
g.drawLine(l.start_x,l.start_y,l.end_x,l.end_y);
}
}
// KeyListenerを実装するためのメソッド
public void keyPressed(KeyEvent e){
// イベントからキーのコードを取り出す
int key=e.getKeyChar();
// デバッグ用の表示
System.out.println("keyPressed("+e+","+key+")");
// 入力が 'q'の時は終了する
if(key=='q') System.exit(0);
}
// 要らないイベントに対応するメソッドも中身は空で書いておく必要がある.
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){}
// MouseListenerを実装するためのメソッド
public void mousePressed(MouseEvent e){
// 押された時のマウスカーソルの位置を得る
int mx=e.getX(),my=e.getY();
// デバッグ用の表示
System.out.println("mousePressed("+e+","+mx+","+my+")");
// 配列linesのlineCount番目に線分を登録
lineArray.addElement(new Line(mx,my,mx,my));
// ドラッグ中であることを示す
dragging=true;
// 再表示をおこなう
repaint();
}
// マウスのボタンが離された時のイベント
public void mouseReleased(MouseEvent e){
// マウスカーソルの位置を得る
int mx=e.getX(),my=e.getY();
// デバッグ用の表示
System.out.println("mouseUp("+e+","+mx+","+my+")");
// 配列linesのlineCount番目の始点を変更
Line l=lineArray.elementAt(lineArray.size()-1);
l.end_x=mx;
l.end_y=my;
dragging=false;
// 再表示をおこなう
repaint();
}
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
// MouseMotionListenerを実装するためのメソッド
public void mouseDragged(MouseEvent e){
// マウスカーソルの位置を得る
int mx=e.getX(),my=e.getY();
// デバッグ用の表示
System.out.println("mouseDrag("+e+","+mx+","+my+")");
// 配列linesのlineCount番目の始点を変更
Line l=lineArray.elementAt(lineArray.size()-1);
l.end_x=mx;
l.end_y=my;
// 再表示をおこなう
repaint();
}
public void mouseMoved(MouseEvent e){}
}
なお,lineArray中の lineCountをマウスを離した時に増やす代わりに,マウ
スを押した際に増やすようにしたため,paint部分が以前と少し変更されてい
ることに注意されたい.
import java.util.*;が必要.
// AWTを使うため,
import java.awt.*;
// イベント駆動関係のクラスを用いるため
import java.awt.event.*;
// Vectorクラスを用いるため
import java.util.*;
// 線分のクラスを定義する.
class Line{
// 始点,終点のX座標,Y座標を int で保持する.
public int start_x,start_y,end_x,end_y;
// Lineのコンストラクタ
public Line(int x1,int x2,int x3,int x4){
start_x=x1;
start_y=x2;
end_x=x3;
end_y=x4;
}
}
// インタフェースの実装では 「implements インタフェース名」と書く
// 複数書く場合は,カンマで区切る
class MouseDraw extends Frame implements KeyListener, MouseListener, MouseMotionListener{
// Lineの配列を保持するVectorクラスの変数 lineArrayの宣言
Vector lineArray;
// マウスをドラッグ中かどうかを示す boolean型(真偽値)の変数draggingの宣言
boolean dragging;
// 表示する色を保持する変数
Color lineColor;
// コンストラクタの宣言
public MouseDraw(String title){
// 親クラス Frameのコンストラクタの宣言
super(title);
lineArray=new Vector();
// ドラッグ中ではない
dragging=false;
// 線の色は黒に
lineColor=Color.black;
// GUI部品と,Event Listenerを関連づける
addKeyListener(this);
addMouseListener(this);
addMouseMotionListener(this);
}
public static void main(String args[]) {
// MouseDrawのインスタンスを作成 frameに代入
MouseDraw frame=new MouseDraw("MouseDraw");
// サイズを 600x400に設定
frame.setSize(600,400);
// 表示する.
frame.setVisible(true);
}
Image offScreenImage;
Graphics offScreenGraphics;
public void update(Graphics g){
if(offScreenImage==null){
offScreenImage=createImage(600,400); // オフスクリーンイメージを600x400のサイズで作成
offScreenGraphics=offScreenImage.getGraphics(); // オフスクリーンイメージに描画するための Graphics オブジェクト
}
paint(offScreenGraphics); // 次の画面のイメージを作る.
g.drawImage(offScreenImage,0,0,this); // イメージを本物のスクリーンに書き込む
}
// offScreenImageの書き直しをする際に呼ばれる
public void paint(Graphics g){
int i;
// 白で(0,0)-(600,400)を塗り潰す
g.setColor(Color.white);
g.fillRect(0,0,600,400);
// 色を設定
g.setColor(lineColor);
int size=lineArray.size();
if(dragging) size--;
for(i=0;i< size;i++){
Line l=(Line)lineArray.elementAt(i);
g.drawLine(l.start_x,l.start_y,l.end_x,l.end_y);
}
// マウスをドラッグ中の時は
if(dragging){
// 赤い色で
g.setColor(Color.red);
// lines[lineCount] を描画する.
Line l=(Line)lineArray.elementAt(i);
g.drawLine(l.start_x,l.start_y,l.end_x,l.end_y);
}
}
// KeyListenerを実装するためのメソッド
public void keyPressed(KeyEvent e){
// イベントからキーのコードを取り出す
int key=e.getKeyChar();
// デバッグ用の表示
System.out.println("keyPressed("+e+","+key+")");
// 入力が 'q'の時は終了する
if(key=='q') System.exit(0);
}
// 要らないイベントに対応するメソッドも中身は空で書いておく必要がある.
public void keyReleased(KeyEvent e){}
public void keyTyped(KeyEvent e){}
// MouseListenerを実装するためのメソッド
public void mousePressed(MouseEvent e){
// 押された時のマウスカーソルの位置を得る
int mx=e.getX(),my=e.getY();
// デバッグ用の表示
System.out.println("mousePressed("+e+","+mx+","+my+")");
// 配列linesのlineCount番目に線分を登録
lineArray.addElement(new Line(mx,my,mx,my));
// ドラッグ中であることを示す
dragging=true;
// 再表示をおこなう
repaint();
}
// マウスのボタンが離された時のイベント
public void mouseReleased(MouseEvent e){
// マウスカーソルの位置を得る
int mx=e.getX(),my=e.getY();
// デバッグ用の表示
System.out.println("mouseUp("+e+","+mx+","+my+")");
// 配列linesのlineCount番目の始点を変更
Line l=(Line)lineArray.elementAt(lineArray.size()-1);
l.end_x=mx;
l.end_y=my;
dragging=false;
// 再表示をおこなう
repaint();
}
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
// MouseMotionListenerを実装するためのメソッド
public void mouseDragged(MouseEvent e){
// マウスカーソルの位置を得る
int mx=e.getX(),my=e.getY();
// デバッグ用の表示
System.out.println("mouseDrag("+e+","+mx+","+my+")");
// 配列linesのlineCount番目の始点を変更
Line l=(Line)lineArray.elementAt(lineArray.size()-1);
l.end_x=mx;
l.end_y=my;
// 再表示をおこなう
repaint();
}
public void mouseMoved(MouseEvent e){}
}