Nanashi-soft○プログラマ専用○Javaアプリケーション○
◎裏画面を使う
点を打つサンプルを実行して,ウィンドウサイズを変えたりしてみると,白くクリアされてしまいます
これは,処理を行った画面が保持されていないからです
裏画面を作成し,そこに処理結果を書き込み,裏画面を実画面にコピーする事で,これを防ぐ事ができます
まず,裏画面用の変数をグローバル変数で定義します
クラス宣言のすぐ下に記述します
public class fst extends Frame{ static Image ura; static Graphics ug; public static final void main(final String[] args){
そして,ウィンドウ表示後に生成します
このタイミングであれば確実にキャンバスの実体がある為です。これより前だとタイミングによってはヌルポインタエラーが出ます
//ウィンドウ表示 app.setVisible(true); //裏画面生成 ura = cvs.createImage(240, 240); ug = ura.getGraphics(); //無限ループ while (true){
そして,ループ中で ugを使用して描画します
paint内に記述していたものを移して,g.の部分を ug.に変えると良いでしょう
※この部分は,後のソース参照のこと
そして,paint内で,裏画面を実画面にコピーします
public void paint(Graphics g){ //裏画面を実画面にコピー g.drawImage(ura, 0, 0, null); }
◎ソース(注意:未完成版)
import java.awt.*; import java.awt.event.*; public class fst extends Frame{ static Image ura; static Graphics ug; public static final void main(final String[] args){ //ウィンドウ生成 Frame app=new Frame(); //タイトル設定 app.setTitle("Title"); //ウィンドウサイズ設定(タイトルや枠も含んだサイズ) app.setSize(240, 240); //キャンバスを配置 fstCanvas cvs=new fstCanvas(); app.add(cvs); //ウィンドウ表示 app.setVisible(true); //裏画面生成 ura = cvs.createImage(240, 240); ug = ura.getGraphics(); //無限ループ while (true){ //座標用変数 int x, y; //カラー用変数 int red, green, blue; //ランダムに座標を生成 x = (int)(Math.random() * 240); y = (int)(Math.random() * 240); //ランダムにカラーを生成 red = (int)(Math.random() * 256); green = (int)(Math.random() * 256); blue = (int)(Math.random() * 256); //ペンの色を変える ug.setColor(new Color(red, green, blue)); //点を描画する ug.drawLine(x, y, x, y); //画面再描画 cvs.repaint(); } } static class fstCanvas extends Canvas{ public void paint(Graphics g){ //裏画面を実画面にコピー g.drawImage(ura, 0, 0, null); } //updateメソッドを乗っ取って,画面クリアを防ぐ public void update(Graphics g){ paint(g); } } }
◎描画タイミングの重要性
上記ソースをビルドして実行してみて下さい
運が良い人は結構多くの点が表示されますが,いつか止まります
環境依存なので,人それぞれだと思います
止まる原因は詳しくは分かりませんが,以下のようなマズい事が起っています
上記ソースでは,
裏画面描画→repaint()→裏画面描画→repaint()→裏画面描画→
と連続して命令を出していますが,描画が完了した事を確認していません
よって,1回目のrepaint()発行後に,まだpaintが終わる前に2回目のreapint()が発行された場合,どのように動作するのかわからない事になります
よって,
裏画面描画→repaint()→描画完了確認→裏画面描画→repaint()→描画完了確認→裏画面描画→
のようにしなければなりません
動画をイメージすると分かり易いと思います
1コマ目生成→描画しろ→描画完了→2コマ目生成→描画しろ→描画完了→
のようにしっかり描画した事を確認しなければ,2コマ目が飛んで3コマ目が表示されてしまい,カクカクした映像になるでしょう
◎ソース
単純にフラグを使用して描画完了をチェックしてみました
import java.awt.*; import java.awt.event.*; public class fst extends Frame{ //裏画面用変数 static Image ura; static Graphics ug; //描画中フラグ static Boolean pflg=false; public static final void main(final String[] args){ //ウィンドウ生成 Frame app=new Frame(); //タイトル設定 app.setTitle("Title"); //ウィンドウサイズ設定(タイトルや枠も含んだサイズ) app.setSize(240, 240); //キャンバスを配置 fstCanvas cvs=new fstCanvas(); app.add(cvs); //ウィンドウ表示 app.setVisible(true); //裏画面生成 ura = cvs.createImage(240, 240); ug = ura.getGraphics(); //無限ループ while (true){ //描画チェックフラグが立っていなければ描画する if (pflg == false){ //座標用変数 int x, y; //カラー用変数 int red, green, blue; //ランダムに座標を生成 x = (int)(Math.random() * 240); y = (int)(Math.random() * 240); //ランダムにカラーを生成 red = (int)(Math.random() * 256); green = (int)(Math.random() * 256); blue = (int)(Math.random() * 256); //ペンの色を変える ug.setColor(new Color(red, green, blue)); //点を描画する ug.drawLine(x, y, x, y); //描画中フラグを立てる pflg = true; //画面再描画 cvs.repaint(); } } } static class fstCanvas extends Canvas{ public void paint(Graphics g){ //描画中フラグが立っていたら処理する if (pflg == true){ //裏画面を実画面にコピー g.drawImage(ura, 0, 0, null); //描画中フラグをクリア pflg = false; } } //updateメソッドを乗っ取って,画面クリアを防ぐ public void update(Graphics g){ paint(g); } } }
これを実行してみると,先程よりも随分遅いと思います
それだけ描画待ち時間があると言うことで,裏画面を2枚にして描画待ち中に次の画面を用意するなど,時間をいかに有効に使うかはプログラマの腕の見せ所でしょう