GUIサーバ高速化/05.部分描画実装(libbaygui)/実装/AWT/03


Top / GUIサーバ高速化 / 05.部分描画実装(libbaygui) / 実装 / AWT / 03

再描画要求

再描画要求を出してどのように処理されるか確認します。 クリックしたときに再描画を要求するテストです。

import java.awt.*;
import java.awt.event.*;

class MyFrame extends Frame {
    public static void main(String args[]) {
        new MyFrame().setVisible(true);
    }
    
    MyFrame() {
        setSize(100, 100);
        addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        add(new MyComponent());
    }
}

class MyComponent extends Component {
    public MyComponent() {
        enableEvents(AWTEvent.MOUSE_EVENT_MASK);
    }
    
    public void paint(Graphics g) {
        Rectangle r = g.getClipBounds();
        g.setColor(Color.RED);
        g.drawRect(r.x, r.y, r.width - 1, r.height - 1);
        System.out.println(r);
    }
    
    protected void processMouseEvent(MouseEvent e) {
        super.processMouseEvent(e);
        if (e.getID() == MouseEvent.MOUSE_CLICKED) {
            repaint(20, 20, 40, 20);
        }
    }
}

クリックしてみたところ、ごく普通に再描画されました。 スクリーンショットの後にログを付けておきます。

repaint-1.png
java.awt.Rectangle[x=0,y=0,width=115,height=66] ← 起動時
java.awt.Rectangle[x=20,y=20,width=40,height=20] ← クリック

タイミング

再描画が掛かるタイミングを調べます。 上のプログラムのMyComponentを変更します。

   protected void processMouseEvent(MouseEvent e) {
       super.processMouseEvent(e);
       if (e.getID() == MouseEvent.MOUSE_CLICKED) {
           System.out.println("<<<");
           repaint(20, 20, 40, 20);
           System.out.println(">>>");
       }
   }

結果は以下の通りです。

java.awt.Rectangle[x=0,y=0,width=115,height=66]
<<<
>>>
java.awt.Rectangle[x=20,y=20,width=40,height=20]

repaint()では要求をキューに溜めるだけで、 その場では描画処理を行っていないようです。 つまり非同期要求です。 Windows用語で言うところのInvalidate(無効化)です。

連続要求

連続した要求がどのように処理されるか調べます

   protected void processMouseEvent(MouseEvent e) {
       super.processMouseEvent(e);
       if (e.getID() == MouseEvent.MOUSE_CLICKED) {
           repaint(20, 20, 40, 20);
           repaint(40, 30, 40, 20);
       }
   }
repaint-2.png
java.awt.Rectangle[x=0,y=0,width=115,height=66] ← 起動時
java.awt.Rectangle[x=20,y=20,width=60,height=30] ← クリック

領域が合成されて一度の描画イベントに統合されました。 隠された部分を表示したときと同じ挙動です。

描画イベント以外での描画

repaint()で間接的にpaint()を呼んで描画しないで、 processMouseEvent()で直接描画してみるとどうなるでしょうか。

   protected void processMouseEvent(MouseEvent e) {
       super.processMouseEvent(e);
       if (e.getID() == MouseEvent.MOUSE_CLICKED) {
           Graphics g = getGraphics();
           g.drawRect(20, 20, 40, 20);
           g.dispose();
       }
   }
repaint-3.png

ごく普通に描画されました。 描画がpaint()に限定されるということはないようです。

update()

それではupdate()の役割は何でしょうか。

   protected void processMouseEvent(MouseEvent e) {
       super.processMouseEvent(e);
       if (e.getID() == MouseEvent.MOUSE_CLICKED) {
           System.out.println("<<<");
           Graphics g = getGraphics();
           g.setClip(20, 20, 40, 20);
           update(g);
           g.dispose();
           System.out.println(">>>");
       }
   }
repaint-1.png
java.awt.Rectangle[x=0,y=0,width=115,height=66]
<<<
java.awt.Rectangle[x=20,y=20,width=40,height=20]
>>>

そのままpaint()を呼び出しているだけのように見えます。 ためしに以下のように変更してみましたがまったく同じ結果でした。

   protected void processMouseEvent(MouseEvent e) {
       super.processMouseEvent(e);
       if (e.getID() == MouseEvent.MOUSE_CLICKED) {
           System.out.println("<<<");
           Graphics g = getGraphics();
           g.setClip(20, 20, 40, 20);
           paint(g);
           g.dispose();
           System.out.println(">>>");
       }
   }

ライトウェイト

そのままpaint()を呼び出すだけなら何のためにあるのかよく分かりません。 ドキュメントを調べてみました。

どうやらライトウェイトとそうではないものとで、 挙動が変わるということのようです。 ピアを使わなければ関係ないため、 ライトウェイト限定でupdate()==paint()と考えても良さそうです。

ちなみに日本語のドキュメントは1.4のものしかありませんが、 ライトウェイトとの関係などが記述されていませんでした。

オーバーライドのことには言及されていますが、 おそらくピアのことを念頭に置いて書かれているのでしょう。

repaint()との関係

ドキュメントにはupdate()はrepaint()から呼ばれるとありました。 そのことを確認してみます。

class MyComponent extends Component {
    public MyComponent() {
        enableEvents(AWTEvent.MOUSE_EVENT_MASK);
    }
    
    public void paint(Graphics g) {
        Rectangle r = g.getClipBounds();
        g.setColor(Color.RED);
        g.drawRect(r.x, r.y, r.width - 1, r.height - 1);
        System.out.println(r);
    }
    
    public void update(Graphics g) {
        System.out.println("{{{");
        super.update(g);
        System.out.println("}}}");
    }
    
    protected void processMouseEvent(MouseEvent e) {
        super.processMouseEvent(e);
        if (e.getID() == MouseEvent.MOUSE_CLICKED) {
            System.out.println("<<<");
            repaint(20, 20, 40, 20);
            System.out.println(">>>");
        }
    }
}
java.awt.Rectangle[x=0,y=0,width=115,height=66]
<<<
>>>
java.awt.Rectangle[x=20,y=20,width=40,height=20]

update()は呼ばれていません。

ピア

ライトウェイトなので自分自身にupdate()が来ない可能性があります。 そこでupdate()のオーバーライドをMyComponentから削除して、 MyFrameに移してみました。

java.awt.Rectangle[x=0,y=0,width=115,height=66]
<<<
>>>
{{{
java.awt.Rectangle[x=20,y=20,width=40,height=20]
}}}

MyFrame#update()からMyComponent#paint()が呼ばれています。 ライトウェイトのupdate()はrepaint()で呼ばれることはないようです。

まとめ

コメント

コメントはありません。 コメント/GUIサーバ高速化/05.部分描画実装(libbaygui)/実装/AWT/03?

お名前:

MENU

now: 1

リンク


最新の20件
2018-05-03 2017-09-29 2017-04-25 2017-01-10 2016-12-11 2016-10-04 2016-08-14 2016-06-05 2016-05-29 2016-04-15 2015-12-28 2013-02-25 2013-02-21 2013-02-20 2013-02-12 2013-02-11 2013-02-10
最新の20件
2010-02-01 2010-01-31 2010-01-30 2010-01-29 2010-01-16

Counter: 2999, today: 2, yesterday: 0

添付ファイル: filerepaint-3.png 328件 [詳細] filerepaint-2.png 314件 [詳細] filerepaint-1.png 303件 [詳細]

リロード   新規 編集 凍結 差分 添付 複製 改名   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新のRSS

Last-modified: 2008-03-28 (金) 15:47:54 (3793d);  Modified by mona
PukiWiki 1.4.6 Copyright © 2001-2005 PukiWiki Developers Team. License is GPL.
Based on "PukiWiki" 1.3 by yu-ji
Powered by PHP 5.2.17
HTML convert time to 0.067 sec.