ログ日記

作業ログと日記とメモ

ゼロから始めるGWT その5

検索していたらGWT Designerというものがあることを知った。
http://junglejava.jp/archives/2010/09/entry_1860.html


オフィシャルはここ?
http://code.google.com/intl/ja/webtoolkit/tools/download-gwtdesigner.html


昔(と言っても最近)は有料だったらしい。
https://www.instantiations.jp/instantiations_price_list_200901.php


今見たら
http://code.google.com/intl/ja/webtoolkit/download.html
ここにリンクが出ている。数日前は無かったと思ったのだが…。



EclipseWidgetを表示するとき、バージョンが古いと

You are attempting to use UiBinder, however your GWT version is old and does
not support the GWT Designer hooks required to provide WYSIWYG editing. You
need at least GWT 2.1M3 for visual editing, and GWT 2.1M4 to also support
the ui:field attribute and the @UiField annotation.

こんなエラーが出るので
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/d5623c7081506cd1/a7929746d020a000?lnk=raot
ここに書いてある通りに
http://code.google.com/p/google-web-toolkit/downloads/list
ここから gwt-2.1.0のmilestone 3 をDLして適当な場所に展開してEclipseの設定に追加する。M4じゃなくてもいいみたい(というか現時点でM4はない)。
設定してもエラーが表示されたままだったのでEclipseを再起動したら表示できた。


この後、ブラウザの表示でエラーが出る。
http://groups.google.com/group/google-web-toolkit/browse_thread/thread/4f480928fd113e22
自動生成されたファイル郡を消して、あとブラウザのキャッシュも消すとエラーが出なくなった。


  • プロジェクトの設定
  • UIの作成
  • Ajaxの処理




というわけで、GWT Designerを使ってHelloサービスを作る。


「新規作成」「WindowBuilder」「GWT Designer」「モデル」「GWT Java Project」と進んでプロジェクト名に「TestApp」、JREはデフォルトのJREを使用にチェックを入れて次へ。Create GWT Moduleのチェックを入れて、Module Nameに「Hello」、パッケージ名に「myapp」を入れて完了。
プロジェクトを右クリックして「プロパティ」から「Google」「Webツールキット」でSDKの構成をクリックして、gwt2.1.0を指定する。
プロジェクトを右クリックして「実行」「GWT Application」でDevelopment Modeが別ウィンドウで立ち上がる。Launch Default Browserをクリックするとブラウザが自動で立ち上がる。このバージョンでは Click me! ボタンが表示されている。



まずはUiBinderを使ってUIを作ろう。
「新規作成」で「UiBinder」「コンポジット」で名前を「TopPanel」にする。
そしてTopPanel.ui.xmlを開いて設計タブで、テキストボックスとボタンを配置する。
テキストボックスのプロパティのUiFieldにtextBox、ボタンのUiFieldにsendButton、HTMLに「送信」を設定する。UTF-8実体参照が気に入らなければXMLソースを開いてそっちの方に日本語を書いてもいい。

それからHello.javaのコードを書き換える。

package myapp.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.RootPanel;

/**
 * Entry point classes define <code>onModuleLoad()</code>.
 */
public class Hello implements EntryPoint {
	public void onModuleLoad() {
		TopPanel root = new TopPanel();
		RootPanel.get().add(root);
	}
}

ここまでで、テキストボックスとボタンが表示されているはず。



次にonClickイベントのコードをTopPanel.javaに書く。初めにTopPanel.ui.xmlを開いて送信ボタンをクリックし、Show events という緑のアイコンがあるのでそれをクリック。割り当て可能なイベント一覧が表示されるので、onClickの右側をダブルクリックすると、TopPanel.javaにコードが挿入される。とりあえずalertでも出しておく。

package myapp.client;

import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.event.dom.client.ClickEvent;

public class TopPanel extends Composite {

	private static final Binder binder = GWT.create(Binder.class);
	@UiField TextBox textBox;
	@UiField Button sendButton;

	interface Binder extends UiBinder<Widget, TopPanel> {
	}

	public TopPanel() {
		initWidget(binder.createAndBindUi(this));
	}

	@UiHandler("sendButton")
	void onSendButtonClick(ClickEvent event) {
		Window.alert(textBox.getValue());
	}
}


次にサービスを作る。
「新規作成」から「モデル」「GWT RemoteService」を選び、サービス名は「HelloService」にする。
HelloService.javaが開かれると思うので、そこにメソッドを定義する。

	public String replyHello(String name);

そうすると、これに対応するコードがHelloServiceAsync.javaとHelloServiceImpl.javaに必要だが、なんと自動で挿入される。


まだ実装がないので、myapp.serverのHelloServiceImpl.javaに実装を書く。

package myapp.server;

import myapp.client.HelloService;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;

@SuppressWarnings("serial")
public class HelloServiceImpl extends RemoteServiceServlet implements HelloService {

	@Override
	public String replyHello(String name) {
		// TODO 自動生成されたメソッド・スタブ
		return "Hello! " + name;
	}
}

TopPanel.ui.xmlに戻って、結果を表示するラベルを配置する。UiFieldはresultLabelにした。
サービスを利用するためのコードをTopPanel.java書く。

public class TopPanel extends Composite {

	private static final Binder binder = GWT.create(Binder.class);
	@UiField TextBox textBox;
	@UiField Button sendButton;

	interface Binder extends UiBinder<Widget, TopPanel> {
	}

	public TopPanel() {
		initWidget(binder.createAndBindUi(this));
	}

	@UiHandler("sendButton")
	void onSendButtonClick(ClickEvent event) {
		HelloService.Util.getInstance().replyHello(textBox.getValue(), new AsyncCallback<String>(){

			@Override
			public void onFailure(Throwable caught) {
				// TODO 自動生成されたメソッド・スタブ
				Window.alert("error: " + caught.getMessage());
			}

			@Override
			public void onSuccess(String result) {
				// TODO 自動生成されたメソッド・スタブ
				Window.alert(result);
			}
			
		});
	}
}


サービスを追加したので一度Development Modeウィンドウを閉じて、再度実行する。
alertが表示されたら成功。



ここで、JavaScriptによるAlertが使いにくいので変更する。
「新規」から「UiBinder」の「DialogBox」を選び、名前をResultDialogにする。ここにはHTMLとボタンを配置する。UiFieldはhtmlとcloseButtonにする。クリック時のイベントはthis.hide()を書く。

public class ResultDialog extends DialogBox {

	private static final Binder binder = GWT.create(Binder.class);
	@UiField HTML html;
	@UiField Button closeButton;

	interface Binder extends UiBinder<Widget, ResultDialog> {
	}

	public ResultDialog() {
		setWidget(binder.createAndBindUi(this));
	}

	@UiHandler("closeButton")
	void onCloseButtonClick(ClickEvent event) {
		this.hide();
	}
}


TopPanel.javaのWindow.alertの部分をResultDialogを使うように書き換える。

public class TopPanel extends Composite {

	private static final Binder binder = GWT.create(Binder.class);
	@UiField TextBox textBox;
	@UiField Button sendButton;
	
	private ResultDialog resultDialog = new ResultDialog();

	interface Binder extends UiBinder<Widget, TopPanel> {
	}

	public TopPanel() {
		initWidget(binder.createAndBindUi(this));
		resultDialog.hide();
	}

	@UiHandler("sendButton")
	void onSendButtonClick(ClickEvent event) {
		HelloService.Util.getInstance().replyHello(textBox.getValue(), new AsyncCallback<String>(){

			@Override
			public void onFailure(Throwable caught) {
				// TODO 自動生成されたメソッド・スタブ
				resultDialog.html.setText("error:" + caught.getLocalizedMessage());
				resultDialog.show();
			}

			@Override
			public void onSuccess(String result) {
				// TODO 自動生成されたメソッド・スタブ
				resultDialog.html.setText(result);
				resultDialog.show();
			}
			
		});
	}
}



ちょっと動きが粗いところもあるけど、初見でも結構使いやすかった。