paintComponentの動作

線描画 方形塗りつぶし描画 楕円描画 文字列描画 外部画像ファイル描画 メモリイメージの描画

以下のパネル上のマウス操作を行い、適当な描画を行った後で、「ダイアログ表示」ボタンをクリックします。 (前ページの続きで、mousePressedの処理は追加済みです)


システムがウインドウのイメージを再描画しなければならないタイミングで、 このpaintComponentのメソッドを呼び出します。(そう作られています)
よって、別のウィンドウなどによって隠されると、paintComponentのメソッド以外で 描画する部分は、無くなってしまいます。
逆にこの中で描いた画像であれば消されても、 隠れた後などのシステムが判断する描画が必要なタイミングで、 自動的にpaintComponentが呼び出されて再描画されるという分けです。
そこで、BufferedImageクラスのメモリイメージを用意します。
そして、paintComponent以外で描画が必要な場合は、 パネルへ直接描画するのではなく、 このでなく、メモリイメージに描画するようにします。 (描く情報をBufferedImageクラスのメモリイメージに記憶するわけです)
そしてpaintComponentの中で、記憶したメモリイメージをパネルへ描画させます。
この直接画面に反映していない記憶域は、オフスクリーンバッファと呼ばれます。 以下で、このイメージを示します。(なお、JPanelを実際に画面へ表示する際に使われるコンピュータ内の 記憶域は、オンスクリーンバッファと呼ばれ、これが変更されると表示が連動して変ります。)

以下で、コードを示します。(前のコードに対してドラックとボタンプレスイベントで行う描画処理は、 全く同じなので、
drawWith(MouseEvent e)メソッドに描画処理を まとめ、各イベントでそれを呼び出すように変更しています。)
←このチェックで、メモリイメージを使うプログラムになります。

package paint;
import java.awt.*;//Point、Color Graphicsなどのパッケージ
import javax.swing.*;//JPanelのパッケージ
import java.awt.event.*;//MouseMotionListenerなどのリスナーや、MouseEventなどのイベント用
import java.awt.image.BufferedImage;//編集可能なメモリイメージ用

//描画対象のパネル
public class PaintPanel extends JPanel implements MouseMotionListener, MouseListener
{
	Image brushImg;//ブラシイメージ管理用
	Image offscrImg = new BufferedImage(250, 250, BufferedImage.TYPE_4BYTE_ABGR);//250×250ピクセルのメモリイメージ

	public PaintPanel() {//コンストラクタ
		
		
		
		
		
		
			

		this.addMouseMotionListener(this);//このクラスに実装したインターフェイスを自身にセット
		this.addMouseListener(this);//マウスのボタン操作メソッドなどがあるオブジェクト指定
	}
	public void paintComponent(Graphics g){//描画すべきタイミングで、呼び出されるメソッド
		super.paintComponent(g);
		
		Color color1 = new java.awt.Color(0x99, 0, 0x0FF);//RGBの色を指定して色を作成
		g.setColor(color1);//描画色設定
		g.drawRect(5, 5, 200, 100);//(5,5)が左上隅の座標で、幅200、高さ100の長方形描画
		g.drawOval(5, 5, 200, 100);//(5,5)が左上隅の座標で、幅200、高さ100の楕円描画
		g.drawImage(offscrImg, 0, 0, this);//メモリイメージをパネルへ描画する追加	
	}
	public void drawWith(MouseEvent e){
		Point p = e.getPoint();//ドラックした所の座標取得
		
		
		
		
		
		this.repaint();
	}
	public void mouseDragged(MouseEvent e){//指定コンポーネントの上で、マウスのボタンを押してドラッグすると呼び出されます。 
		drawWith(e);
	}
	public void mouseMoved(MouseEvent e) {//ボタンを押さずに、マウスを指定コンポーネントで移動すると呼び出されます。 
	}
	public void mouseEntered(MouseEvent e){// コンポーネントにマウスが入ると呼び出されます。
	}
	public void mousePressed(MouseEvent e){// コンポーネント上でマウスボタンが押されると呼び出されます。 
		drawWith(e);
	}
	public void mouseReleased(MouseEvent e){// コンポーネント上でマウスボタンが離されると呼び出されます。 
	}
	public void mouseClicked(MouseEvent e){//マウスクリック
	}
	public void mouseExited(MouseEvent e){//コンポーネントからマウスが出ると呼び出されます。 
	}
}

補足

paintComponentをオーバーライドメソッドを作る場合、スーパークラスのメソッドも実行させる次の処理が必要です。

	super.paintComponent(g);//元々存在するスーパークラスの処理も行う!

これを行わない ( ) 時、ドラック描画して、他のウインドウでパネルの一部を隠してから、 再びドラックすると描画に不具合が確認されるでしょう。
swingコンポーネント(JPanelなどすべて)の描画は、 Windowsシステムからの描画依頼に応じて、 親のコンポーネントからrepaintメソッドが呼び出され、 それによってupdateメソッドによるコンポーネントの更新が行なわれて paintメソッドによるコンポーネントへの描画行なわれます。
paintメソッドの中では、paintComponentメソッドによるコンポーネント描画が行なわれ、 paintBorderメソッドによるボーダー(コンポーネントの周囲の描画)の描画が行なわれ、 次にpaintChildrenメソッドによって内部に配置されるコンポーネントの描画・・・と進みます。
つまりあらかじめ作られている処理を飛ばして、自分が行いたい描画処理だけを書くと、 処理されない部分的で不具合が起きるということです。

以上の各プログラムを確認したらこのボタンをクリックください。→