注意するのは,repaintの呼び出しが1対1でupdateに対応しているわけでない ことです.repaintはシステムに対して,暇になったらなるべく早くupdateを 呼んでくれと依頼するだけなので,暇でない時に repaintを何度も呼び出すと, 暇になってから1回だけ updateが呼ばれるということになります.
解答例
// AWTを使うため,
import java.awt.*;
// イベント駆動関係のクラスを用いるため
import java.awt.event.*;
// 長方形のクラスを定義する.
class ColorRect{
// 始点,終点のX座標,Y座標を int で保持する.
public int start_x,start_y,end_x,end_y;
public Color color;
// ColorRectのコンストラクタ
public ColorRect(int x1,int x2,int x3,int x4,Color col){
start_x=x1;
start_y=x2;
end_x=x3;
end_y=x4;
color=col;
}
}
// インタフェースの実装では 「implements インタフェース名」と書く
// 複数書く場合は,カンマで区切る
class MouseDraw extends Frame implements KeyListener, MouseListener, MouseMotionListener{
// Rectの配列を保持する変数 rectsの宣言
public ColorRect[] rects;
// rectsのどこまで使われているかを示す変数 rectCountの宣言
int rectCount;
// マウスをドラッグ中かどうかを示す boolean型(真偽値)の変数draggingの宣言
boolean dragging;
// 表示する色を保持する変数
Color rectColor;
// コンストラクタの宣言
public MouseDraw(String title){
// 親クラス Frameのコンストラクタの宣言
super(title);
// 大きさ10のColorRectの配列を作成してrectsに代入
rects=new ColorRect[10];
// rectsは何も使われていない
rectCount=0;
// ドラッグ中ではない
dragging=false;
// 線の色は黒に
rectColor=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);
// 色を設定
// rectCount個,rectsに登録されているrectsを描画する
for(i=0;i< rectCount;i++){
g.setColor(rects[i].color);
int minx=Math.min(rects[i].start_x,rects[i].end_x);
int maxx=Math.max(rects[i].start_x,rects[i].end_x);
int miny=Math.min(rects[i].start_y,rects[i].end_y);
int maxy=Math.max(rects[i].start_y,rects[i].end_y);
g.fillRect(minx,miny,maxx-minx,maxy-miny);
}
// マウスをドラッグ中の時は
if(dragging){
// 赤い色で
g.setColor(Color.red);
// rects[rectCount] を描画する.
int minx=Math.min(rects[i].start_x,rects[i].end_x);
int maxx=Math.max(rects[i].start_x,rects[i].end_x);
int miny=Math.min(rects[i].start_y,rects[i].end_y);
int maxy=Math.max(rects[i].start_y,rects[i].end_y);
g.drawRect(minx,miny,maxx-minx,maxy-miny);
}
}
// KeyListenerを実装するためのメソッド
public void keyPressed(KeyEvent e){
// イベントからキーのコードを取り出す
int key=e.getKeyChar();
// デバッグ用の表示
System.out.println("keyPressed("+e+","+key+")");
// 入力が 'q'の時は終了する
if(key=='r') rectColor=Color.red;
else if(key=='g') rectColor=Color.green;
else if(key=='b') rectColor=Color.blue;
else 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+")");
// 配列rectsのrectCount番目に線分を登録
rects[rectCount]=new ColorRect(mx,my,mx,my,rectColor);
// ドラッグ中であることを示す
dragging=true;
// 再表示をおこなう
repaint();
}
// マウスのボタンが離された時のイベント
public void mouseReleased(MouseEvent e){
// マウスカーソルの位置を得る
int mx=e.getX(),my=e.getY();
// デバッグ用の表示
System.out.println("mouseUp("+e+","+mx+","+my+")");
// 配列rectsのrectCount番目の始点を変更
rects[rectCount].end_x=mx;
rects[rectCount].end_y=my;
// rectCountを増やす
rectCount++;
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+")");
// 配列rectsのrectCount番目の始点を変更
rects[rectCount].end_x=mx;
rects[rectCount].end_y=my;
// 再表示をおこなう
repaint();
}
public void mouseMoved(MouseEvent e){}
}