GUIサーバ高速化/06.AWT調査後の方針/具体的に


Top / GUIサーバ高速化 / 06.AWT調査後の方針 / 具体的に

前提

講評

../に関して。あくまでTinoの感想なので、 客観的な評価である保証はありません。 「お前の独善だ」等の批判は甘んじてお受けします。 自分でも正しいことを言っているという自信があるわけではないので、 漸近線的に妥協点に近付ければと思っています。

  1. お礼
    • これだとまるで人事です。とげがあるのではっきり言いませんでしたが、私は間接的に、本来こういう調査を人に頼らずに自分でやるべきだと言っています。
    • というわけで人事扱いしないで、自分でやるとすればどうなんだろう、という観点で考えていただきたいと思います。
    • 時間がなくてできなければ、誰かに指示してやらせれば良いので、時間的にできないということは拒否の理由になりませんので悪しからず。
    • 調査に関しては、AWTの解説を探して引用するようなことをしないで、簡単なコードで探りを入れるという方法を示しました。こういう方法のことを「帰納的」と表現しています。作業の際にどのようなことを考えたかをいちいち書いたので時間がかかりましたが、作業量そのものは大したことありません。
      • 他人事であるような伝わり方は良くないという点には同意です。質問1.「他人事と読み取れたのはどこでしょうか」、質問2.「お礼を書くのはあたり前で一番最初に書くべきだと思ったのですがお礼を書くことも否定されていますか?」 -- ひげぽん
  2. 現状問題点
    • これは基本的にOKです。一点だけ引っ掛かりました。↓
    • 「部分描画を指示する repaint(x, y, w, h)が用意されていない。」いきなりrepaint(x, y, w, h)が出てきています。妥当性はAWTの実装を引き合いに示すべきです。
      • 同意です。 -- ひげぽん
  3. 今回の対応へのスタンス
    • これは蛇足に感じます。いきなりスタンスと言われると、上から見下ろしているような印象を受けます。
    • 具体的な工程を書けば、スタンスを書く必要はないでしょう。
    • スタンスを表明するなということではありません。工程に対して突込みがあった場合に、背景として説明すれば良いでしょう。背景を前に持ってくるのに違和感があるということです。
    • 下で感想は好印象だと述べていますが、感想のような形でスタンスを挿入して補足するのは大いに結構です。これは単に私の好みで、トップダウンよりボトムアップの方が印象が良いというだけのことなんですけど。
      • スタンスを書いたのは理想形→妥協点の根拠を事前に示したかったからです。更に該当ページを読むだけで私の意見がスタンスを含めて理解されるように意図して書いています。(突っ込まれるまえに書いたということです)。背景がどこにかかれるべきかにはこだわりがないので、後ろでも良いとは思います。 -- ひげぽん
  4. 理想形
    • AWTの実装に合わせるという観点ではなく、アプリ側のコードの記述で基本的な考え方が踏襲できるかどうかという観点が重要です。
  5. 現実的な解
    • スタンスと同様で、具体的な工程を記述すれば、書かなくても構わないでしょう。
    • 工程うんぬんというのは、数学のイメージでいけば、ごちゃごちゃと計算したりする過程を示すように、ということです。計算過程を省いて結論だけ書いてあるので、数学のテストでは残念ながら・・・という感想を持ちました。
      • これは結論だけでは、途中の思考過程がTinoさんやBaysideさんに伝わらなかったということでしょうか。それとも詳しくない人が読んだときに理解されないだろうということでしょうか。後者なら納得できそうです。
  6. その他の点について
    • 結果を記述するという観点からは蛇足といえば蛇足なのですが、個人的には、こういう感想を読むと人間性に触れられるので大好きです。
    • そのため私は意図的に、作業の後に感想を書くようにしています。これは完全に私の好みです。客観的な推奨理由はありません。
  7. 蛇足
    • この話は以前からきちんと煮詰めようと思っていたものなので、今すぐ議論するようなことではないにしても、スタックに積んでおきましょう。
    • 見解の相違がスタンスではなく誤解に基づくのではないかという部分があるので、突っ込みました。話題を避けていると、誤解が解ける機会もなくなるので、無視するわけにはいかないと感じました。
      • こういう話は飲みながら話した方が良いのかも知れませんね。文章は意図せず刺があるように読まれてしまいますし、リアルタイムに補足説明ができる方が有利でしょう。非現実的かもしれませんけど。 -- ひげぽん

具体的に

導入として、ひげぽんさんが書いておられるように、 「全体描画しかしなくて部分描画がないため遅い」ということ書くのは良いです。 それでどうするかですが、

  1. BayGUIはなるべくAWTと同じにするという方針は判明している。
  2. 本物のAWTを調べるとrepaint(x, y, w, h)がある。
  3. repaint(x, y, w, h)を実装してみよう。

こういう流れが書いてあると背景がはっきりします。 1と2が省略されているので、 結論しか書かれていないという感想を持ちました。

Test First

それで実装する前に、どういうコードを期待した改造なのか、 ということをはっきりさせると良いです。 いわゆるTest Firstの考え方です。 これはひげぽんさんご自身の手で書いておられることですが、 是非まとめでも具体的に言及しましょう。

void Canvas::drawSomething()
{
    count++;
    Graphics* g = getGraphics();
    g->setColor(Color::white);
    g->fillRect(10, 10, 30, 30);
    g->setColor(Color::green);
    char buf[32];
    sprintf(buf, "%d", count);
    g->drawString(buf, 15, 15);
    repaint(10, 10, 30, 30);
}

Test Firstとまで厳密に考えなくても、 この手のことは疑似コードとしてイメージで用いられたりもします。 こういう動きをしたらいいな、というのが先にあって、 それを実現するにはどうしたら良いのかということを考えるので、 これも帰納的な手法だと言えます。

参考までに逆の演繹的な手法のことを書くと、 APIなどを先に決めておいてから、 それをどう組み合わせてアプリを書くか考える形になります。 これはこれで否定するわけではないので念のため。

AWTとの整合性

上の想定コードはAWT的にどうよ?というのは当然気になることです。

まずpaint()の外で描画することに関しては問題ありません。 本物のAWTで以下のようなコードが動きます。

  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()など使っていないということです。 それではrepaint()を使うとどうなるか? 白抜きになってしまいます。 これはrepaint()が描画範囲をクリアする仕様だからです。

そのため上のTest FirstのコードをAWTで実行すると 何も描画されないという結果になってしまいます。 BayGUIはAWTと違うと割り切れば済む問題かもしれませんが、 それを押し切るには何らかの根拠が必要です。

辻褄合わせ

GUIサーバーはダブルバッファを強制します。 AWTはダブルバッファをしてくれません。 このことを折衷させると、 AWTでダブルバッファをさせたときに どのようなコードを書くことになるかという話になります。

AWTでダブルバッファをさせると次のようになります。

   public void validate() {
       super.validate();
       enableEvents(AWTEvent.MOUSE_EVENT_MASK);
       buffer = createImage(200, 200);
   }

   public void paint(Graphics g) {
       g.drawImage(buffer, 0, 0, this);
   }
   
   protected void processMouseEvent(MouseEvent e) {
       super.processMouseEvent(e);
       if (e.getID() == MouseEvent.MOUSE_CLICKED) {
           int x = e.getX(), y = e.getY();
           Graphics g = buffer.getGraphics();
           g.drawRect(x - 5, y - 5, 10, 10);
           g.dispose();
           repaint(x - 5, y - 5, 11, 11);
       }
   }

描画してからrepaint()というアルゴリズムは同じです。 BayGUI改造案と比べてAWTの違いは次の通りです。 dispose()は書かなくても動くので無視します。

  1. bufferを作っている
  2. paint()で自前ダブルバッファしている
  3. getGraphics()をthisではなくbufferに対して行っている

この辺の差異は構造の違いに起因するため妥協するという前提で実装します。 これをはっきりさせないといけないのは、明らかにAWTと違う部分なので、 説明がないと後々BayGUIを使ってアプリを作る人が、 試行錯誤する羽目になってしまうからです。 その辺を割り切った方針であると断っておかないと、 後で絶対に地雷になります。

ここまでが調査結果を引用して明確にするべきだと考えている点です。 かなり冗長に書きましたが、趣旨が伝わればもっと省略しても構いません。 ここで注意して欲しいのは、以下のことを要求していることです。

実装

あとは実装を箇条書きすれば充分です。

  1. 【追加】Component::repaint(x, y, w, h)
    void Component::repaint(int x, int y, int w, int h)
    {
      if (this->_buffer == NULL) return;
      update(x, y, w, h);
    }
    • 【補足】これを追加することは最初に断っているので、追加の根拠の説明は不要。
  2. 【追加】Graphics::drawImage(image, x, y, w, h, componentX, componentY)
    • 部分描画のためのメソッドを追加。
  3. 【修正】Component::update(x, y, w, h)
    • repaintから呼び出される
    • 追加した部分描画のdrawImage()を使用
      - c->getGraphics()->drawImage(this->_buffer, getX(), getY());
      + c->getGraphics()->drawImage(this->_buffer, x, y, w, h, getX(), getY());
      • ↑で(x, y)がローカル座標系を前提にしているため↓
    • グローバル座標系からローカル座標系に修正
      - c->update(c->getX() + c->getInsets()->left + x,
      -   c->getY() + c->getInsets()->top + y, w, h);
      + c->update(c->getX() + c->getInsets()->left + x + getX(),
      +   c->getY() + c->getInsets()->top + y + getY(), w, h);

以上はひげぽんさんが行った修正をまとめただけです。 ここではレポートのまとめ方だけを問題にしているため、 修正に対する意見などは回を改めて扱います。

コメント

コメントはありません。 コメント/GUIサーバ高速化/06.AWT調査後の方針/具体的に?

お名前:

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: 2025, today: 1, yesterday: 0

リロード   新規 編集 凍結 差分 添付 複製 改名   トップ 一覧 検索 最終更新 バックアップ   ヘルプ   最終更新の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.070 sec.