2010年09月05日

vaadinでちょっとはまりました フラグメント管理

vaadinで画面を作成しようとしてはまってしまった罠(?)をご紹介します。
フラグメント管理ですっきり画面の制御をしようと、
Javaで軽快に使える「軽量フレームワーク」特集 〜リッチなGUIを構築する「Vaadin」(3)
を参考に試していたところ、サブウィンドウでこのテクニックを使用しようとしてうまく制御ができませんでした。
どんなことをしていたかと言うと、
 @サブウィンドウで一種のウィザードのような2ページで遷移する画面を作成
 Aサブウィンドウの2ページは「UriFragmentUtilityによるフラグメント管理」をもちいる
 Bサブウィンドウは処理を完了すると画面を閉じる
上記のようなことをしていました。
最初にサブウィンドウを開いた際には思い通りの制御ができていたのですが、2度目以降は前回のフラグメントが残っていて、サブウィンドウはいきなり2ページ目が表示されてしまいました。
簡単に要素となる部分のみのコーディングを示すと下記のようになります。
public class SubWindow extends Window {
  private Layout contextLayout;
  private Layout firstPage;
  private Layout secondPage;
  private UriFragmentUtility urifu = new UriFragmentUtility();
  ・・・
  public SubWindow() {
    contextLayout = (VerticalLayout) getContent();
    firstPage = createFirstPage();
    secondPage = createSecondPage();
    addComponent(urifu);
    urifu.addListener(new FragmentChangedListener() {
      public void fragmentChanged(FragmentChangedEvent source) {
        String s = source.getUriFragmentUtility().getFragment();
        if ("firstPage".equals(s)){
          contextLayout.addComponent(firstPage);
          contextLayout.removeComponent(secondPage);
        } else {
          contextLayout.removeComponent(firstPage);
          contextLayout.addComponent(secondPage);
        }
      }
    });
    contextLayout.addComponent(firstPage);
  }
  private Layout createFirstPage() {
    VerticalLayout layout = new VerticalLayout();
    Button button = new Button("次へ", new Button.ClickListener() {
      public void buttonClick(ClickEvent event) {
        ・・・
        urifu.setFragment("secondPage", true);
      }
    });
    layout.addComponent(button);
    return layout;
  }
  private Layout createSecondPage() {
    VerticalLayout layout = new VerticalLayout();
    Button button = new Button("実行", new Button.ClickListener() {
      public void buttonClick(ClickEvent event) {
        ・・・
        ((Window) getParent()).removeWindow(getWindow());
      }
    });
    layout.addComponent(button);
    return layout;
  }
}
2ページめのボタンクリックでフラグメントをセットしても、メイン画面に戻ってきた際にはフラグメントが残ったままになってしまうようです。
また、サブウィンドウのコンストラクタでフラグメントを初期化しても、前回のフラグメントが有効なのか、一瞬にして2ページ目に遷移してしまいます。
深く内部的な部分まで追えませんでしたが、イベントが発生するタイミングや、クライアント側のオブジェクトの持ち方などに関係していそうです。
結局フラグメントのイベントはあきらめ、直接コンポーネントを制御する方法をとりました。
ページ制御を行う関数を用意し、
  private void switchPage(String pageName) {
    if ("firstPage".equals(pageName)){
      contextLayout.addComponent(firstPage);
      contextLayout.removeComponent(secondPage);
    } else {
      contextLayout.removeComponent(firstPage);
      contextLayout.addComponent(secondPage);
    }
  }
ボタンはこの関数を呼ぶように変更します。
    Button button = new Button("次へ", new Button.ClickListener() {
      public void buttonClick(ClickEvent event) {
        ・・・
        switchPage("secondPage");
      }
    });
これで思い通りの動作をしてくれる画面ができました。
よくよくソースを見比べると、フラグメントのチェンジイベントによる制御と、関数呼び出しによる制御で、ほとんど変わっていないことがわかります。
せっかくある技だからと、少し時間をかけすぎたことを反省しています。
posted by しん at 07:48| Comment(0) | vaadin | このブログの読者になる | 更新情報をチェックする
この記事へのコメント
コメントを書く
お名前:

メールアドレス:

ホームページアドレス:

コメント:

認証コード: [必須入力]


※画像の中の文字を半角で入力してください。
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。