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


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

はじめに

Javaのことはほとんど知らない初心者です。 環境構築などどこから手を付けて良いのか手探り状態のため、 NetBeans付きのJDKを入れてNetBeansを使用します。

NetBeansはかなり昔に起動だけさせたことがありますが、 まともに使ったのはこれが初めてです。 以前Eclipseは使ったことがありますが、 JavaではなくC++でMonaの開発しかしませんでした (その当時の残骸⇒Eclipse)。 SALを使わなかったのは、 当時Windowsでまともに動かなかったのと、 私が誰かバレてしまうのを危惧したからです。 結局バレてしまいましたが……。

フレームを表示

AWT用語でトップレベルウィンドウのことをフレーム(Frame)と呼ぶようです。

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

class Main {
    public static void main(String args[]) {
        Frame f = new Frame();
        f.setSize(300, 200);
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        f.show();
    }
}

f.show();が非推奨APIだと警告されてしまいました。 f.setVisible(true);と書くのが推奨されているようです。

よく見るとこのコードは不思議です。 main()から出てすぐ終了してしまいそうなものですが、 終了せずにGUIが動いています。 多分GUIスレッドが起こされてそちらが続行しているのでしょう。

f.show();の前後にSystem.out.println("-");を挟んでみましたが、 そこでブロックされているわけではないということは確認しました。

どうでも良いことですが、NetBeansの括弧自動生成機能が、 私が以前考えたものと同じだったので驚きました。 閉じ括弧が自動生成されても入力すればスルーされる機能です。 これは私が先に考えたと主張したいわけではまったくなくて、 むしろ同じことを考える人がいるんだなと安心しました。 独創的というのは独り善がりに陥りがちなので、 同じアイデアを見掛けると安心するということです。 個人的に技術は没個性的なものの方が安心できます。

描画

描画の挙動の調査が目的なので早速やります。

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

class MyFrame extends Frame {
    public static void main(String args[]) {
        MyFrame f = new MyFrame();
        f.setSize(300, 200);
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        f.setVisible(true);
    }
    
    public void paint(Graphics g) {
        g.drawLine(0, 0, getWidth(), getHeight());
    }
}
MyFrame.png

ここでちょっと驚いたのは、オフセットが抽象化されていないということです。 マルチプラットフォームツールキットでは当たり前だと思い込んでいましたが、 いかに自分が無知かということを痛感しました。 新しい物に触れると色々と発見があってスリリングです (という気持ちを失わないようにしたいという希望半分)。

※オフセットの概念は../../コメントを参照してください。

コメント

J#

ふと、MSの実装ではどうなっているのか気になりました。 そこで一度も使ったことのないJ#を使ってみることにしました (VS.NET 2003は既にインストールされているためすぐに使えます)。

するとgetWidth(), getHeight()がないというエラーになりました。 NetBeansで調べてみると、JDK 1.2で導入されたとのことです。 MSの実装は1.1で止まっているということを今更ながら体験してしまいました。

仕方ないのでgetSize().width, getSize().heightと書きましたが、 ドキュメントにはヒープが無駄になるため、 getWidth()などを使う方が好ましいと書いてありました。 でもないものはないので、どうしようもありません。 とりあえずgetSize()を変数に入れることにします。

Dimension s = getSize();
g.drawLine(0, 0, s.width, s.height);
MyFrame-2.png

同様にオフセットを無視した描画がなされました。 おお、ちゃんと互換性が取れていますね!

やっぱりVS.NETは慣れているので安心して使えます。 NetBeansはやめてJ#で検証をしようかと一瞬思いました。 でもせっかく新しい物に触れて色々と驚いているのに、 古巣(?)に戻ってしまうと意味ないじゃないかと思い直しました。

子ウィンドウ

子ウィンドウを配置して座標系を確認します。

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);
            }
        });
        setLayout(null);
        MyCanvas c1 = new MyCanvas();
        MyCanvas c2 = new MyCanvas();
        c1.setBounds(10, 10, 30, 30);
        c2.setBounds(50, 50, 30, 30);
        add(c1);
        add(c2);
    }
    
    class MyCanvas extends Canvas {
        public void paint(Graphics g) {
            Dimension s = getSize();
            g.drawLine(0, 0, s.width, s.height);
            g.drawRect(0, 0, s.width - 1, s.height - 1);
        }
    }
}
MyFrame-3.png

JDKとJ#を並べて比べてみました。 オフセットは考慮されない配置になっています。

MyCanvasをCanvasではなくComponentを継承させてみました。 結果、まったく見た目に変化がありませんでした。

ライトウェイト

Swingはライトウェイトであるということが特徴だとされています。 ライトウェイトとはピアのリソースを使わないということで、 動作の軽さのことを指しているわけではありません。

そこでCanvasとComponentを並べてみました。

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);
            }
        });
        setLayout(null);
        Component c1 = new Component() {
            public void paint(Graphics g) {
                Dimension s = getSize();
                g.drawLine(0, 0, s.width, s.height);
                g.drawRect(0, 0, s.width - 1, s.height - 1);
            }
        };
        Canvas c2 = new Canvas() {
            public void paint(Graphics g) {
                Dimension s = getSize();
                g.drawLine(s.width, 0, 0, s.height);
                g.drawRect(0, 0, s.width - 1, s.height - 1);
            }
        };
        c1.setBounds(10, 10, 30, 30);
        c2.setBounds(50, 50, 30, 30);
        add(c1);
        add(c2);
    }
}

Sunの実装でこれを実行してSpy++で調べてみました。 見事にCanvasだけネイティブウィンドウを伴っています。

Spy.png

しかしJ#で同じものを実行させたところCanvasはウィンドウを伴いませんでした。 SunとMSの実装が違う点がついに出て来ました! ただし動作は互換なので問題になることはないと思いますが。 ともかく敢えてCanvasを使う意味はほとんどなさそうです。

この結果を見て、 MonaのGUIでもサーバーではトップレベルウィンドウだけを提供すれば 充分なのではないかと思いました。 その上に置くものはクライアント側でライトウェイトに実装すれば良いからです。 それが可能であることはSwingが証明しています。

そしてこの構造はサーバーとクライアントで相似である事に気付きました。 サーバーでスクリーンにウィンドウを描画するのと同じように、 クライアントではウィンドウにコンポーネントを描画するからです。 重ね合わせ描画などのコードが共有できそうです!

コメント

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

お名前:

MENU

now: 3

リンク


最新の20件
2018-09-03 2018-05-09 2017-09-29 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: 3043, today: 1, yesterday: 0

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

Last-modified: 2008-03-28 (金) 15:47:54 (3831d);  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.044 sec.