以下のパネル上のマウス操作を行い、適当な描画を行った後で、「ダイアログ表示」ボタンをクリックします。 (前ページの続きで、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メソッドによって内部に配置されるコンポーネントの描画・・・と進みます。
つまりあらかじめ作られている処理を飛ばして、自分が行いたい描画処理だけを書くと、
処理されない部分的で不具合が起きるということです。
以上の各プログラムを確認したらこのボタンをクリックください。→