GWTコンポーネントの詳細
今度はGWTコンポーネントに親しむために、このアプリケーションの中身を覗いてみましょう。
HTMLホストページ:Hello.html
GWTのAJAXでは、クライアントのアプリケーションロジックはすべて、ホストページと呼ばれる単独のHTMLページに記述されます。「public」フォルダ内の「Hello.html」ファイルは、このようなホストページの1つです。このファイルには、ユーザーとの対話のロジックとユーザーインターフェイスを実現するJavaScriptが含まれています。「Hello.html」ファイルは<script language="javascript" src="gwt.js"></script>タグを介してこのJavaScriptを取得し、<meta name='gwt:module' content='com.techyatra.awe.Hello'>タグはそれをGWTモジュールにリンクさせます。
モジュール:Hello.gwt.xml
「Hello.gwt.xml」ファイルには、GWTアプリケーションのロジック部分を実現するモジュールが含まれています。com.techyatra.aweにあるこの「Hello.gwt.xml」ファイルは、com.techyatra.awe.HelloというGWTモジュールを表しています。「Hello.gwt.xml」を含むフォルダは、AJAX With Easeアプリケーションのルートフォルダと見なされます。GWTでは、最終的に「client」フォルダおよび「public」フォルダに格納されるモジュールのJavaソースファイルおよびHTMLファイルを、このcom.techyatra.aweルートフォルダの下に置く必要があります。
AJAX With Easeアプリケーションの「Hello.gwt.xml」ファイルには、このアプリケーションが継承するベースモジュール(com.google.gwt.user.User)と、RPC通信のためのサーブレットパスおよび実装クラス、さらにJavaのpublic static main(String[] args)関数に類似したインターフェイスを実装する叩き台クラス(EntryPoint)が含まれています。以下に、「Hello.gwt.xml」モジュールファイルのリストを示します。
<module> <!-- Inherit the core Web Toolkit--> <inherits name='com.google.gwt.user.User'/> <!-- Ajax with Ease app entrypoint class--> <entry-point class='com.techyatra.awe.client.Hello'/> <!-- GWT's RPC Servlet path--> <servlet path='/hello' class='com.techyatra.awe.server.HelloServiceImpl'/> </module>
EntryPoint
ちょうどJavaアプリケーションがpublic static main(String [] arg)関数を持つクラスを必要とするように、GWTにはcom.google.gwt.core.client.EntryPointを実装するクラスが必要です。これはpublic void onModuleLoad()という関数だけを含む単純なインターフェイスです。
AJAX With Easeアプリケーションの場合は、com.techyatra.awe.client.HelloクラスがこのEntryPointインターフェイスを実装しています。以下のリストに、「Hello.java」ファイルを使った実装を示します。
package com.techyatra.awe.client; ... /** * Entry point classes define <code>onModuleLoad()</code>. */ public class Hello implements EntryPoint { private HelloRPC helloRPC = new HelloRPC(); private HelloCSS helloCSS = new HelloCSS(); private HelloHistory helloHistory = new HelloHistory(); ... /** * This is the entry point method. */ public void onModuleLoad() { button.addClickListener(new ClickListener() { ... }); tabs.add(helloCSS, "Styles"); ... RootPanel.get("slot1").add(label); RootPanel.get("slot2").add(button); RootPanel.get("slot3").add(tabs); } }
GWTの場合、onModuleLoad()はアプリケーションのエントリポイントとしてだけでなく、事実上のコンストラクタとしても機能します。この関数は、コンパイルされたJavaScriptコードにおいて最初に実行されます。普通はonModuleLoad()関数にGWTのウィジェット、パネル、コンポジットといったユーザーインターフェイスコンポーネントを作成するコードを追加することになります。作成が終わって準備が整うと、これらのコンポーネントはRootPanelを介してHTMLページに追加されます。
RootPanel
com.google.user.client.ui.RootPanelは、JavaコードをHTMLページに、ひいてはブラウザのwindowオブジェクトに関連付けるパイプの役割を果たします。GWTコンポーネントをブラウザのwindowオブジェクトに追加するには、次の2つの方法があります。
- GWTのJavaベースのレイアウトマネージャを使って完全なユーザーインターフェイスをコード内に作成し、
RootPanel.get().add(your container object)を呼び出すことで、そのコンテナインスタンスをRootPanelに追加します。この方法では、インターフェイス全体はJavaコード内に存在し、実行時にJavaScriptによって生成されます。 - HTMLと動的なコードベースのインターフェイス生成を組み合わせます。この方法では、以降も引き続きWeb開発者が複雑なレイアウトとグラフィックを備えたWebページを作成することになります。ただし、コントロールはJavaコードによって動的に作成されるので、そのプレースホルダを指定します。最終的には、GWTのJavaコードによってこれらのプレースホルダに適切なコントロールが配置されます。
上記1の方法、つまりJavaだけを使ってUIを作成するという方法は、グラフィックが少なくレイアウトがシンプルでGoogleに類似したインターフェイスのアプリケーションに向いています。一方、グラフィックやレイアウトを重視するようなアプリケーションには上記2の方法を検討するとよいでしょう。
プレースホルダやスロットはHTMLファイル内に配置できます。これらのスロットに、「Hello.java」ファイルのRootPanel.get(slot name).add(your widget)を使って適切なコントロールを差し込みます。
... <table align=center> <tr> <td id="slot1"></td><td id="slot2"></td> </tr> </table> ...
...
RootPanel.get("slot1").add(label);
RootPanel.get("slot2").add(button);
...
HTMLとコードを組み合わせる方法では、Web開発者が美しいレイアウトやグラフィックを担当し、Javaプログラマがより軽快なアプリケーションの実装を担当するという分担ができます。
UIコンポーネント:ウィジェットとパネル
Java Swingと同様、GWTにもレイアウトマネージャとGUIコントロールが付随していますが、GWTではこれらをそれぞれ「パネル」と「ウィジェット」と呼びます。ウィジェットは、ユーザーが直接操作できるユーザーコントロールです。GWTウィジェットの例としてはButton、RadioButton、TextBox、TabBar、Tree、MenuBarなどがあります。これらのウィジェットはパネル内に配置され、ウィジェットの配置およびレイアウトはパネルによって決定されます。GWTのパネルにはHorizontalPanel、VerticalPanel、DockPanelなどがあります(GoogleのGWTドキュメントにはパネルおよびウィジェットの全リストがあります)。
こうしたパネルおよびウィジェットの使い方や動作もまたJava SwingのGUIコンポーネントに似ています。これらのコンポーネントはプロパティの設定および取得を行うメソッドを持ち、通常のキーおよびマウス操作のイベントを扱うためのイベントリスナモデルをサポートしています。次のコードは「Hello.java」クラスの一部であり、簡単なGWTボタンを生成したうえでオーバライドし、クリックリスナを提供します。
... public class Hello implements EntryPoint { final Button button = new Button("Hello"); ... public void onModuleLoad() { button.addClickListener(new ClickListener() { public void onClick(Widget sender) { ... } }); } ... }
ウィジェットとパネルは便利なものですが、複雑なユーザーインターフェイスを作成するにはパッケージ化と、これらのインターフェイスに視覚的な装飾を施す機能が必要です。それでは、続いてコンポジットとカスケーディングスタイルシート(Cascading Style Sheets:CSS)について説明しましょう。
コンポジット
GWTでは、ウィジェットおよびパネルのグループを結合して、コンポジットと呼ばれる独立したウィジェットを新たに作成できます。次のリストは、ボタンとパネルを結合してHelloCSSという便利で独立したコンポジットを作成する方法を示しています。
package com.techyatra.awe.client; ... public class HelloCSS extends Composite { final Button buttonCSS = new Button("Apply Style"); final VerticalPanel panel = new VerticalPanel(); public HelloCSS() { buttonCSS.addClickListener(new ClickListener() ... buttonCSS.addStyleName("awe-button"); ... ); panel.setHorizontalAlignment(panel.ALIGN_CENTER); panel.add(buttonCSS); setWidget(panel); } }
このHelloCSSウィジェットは「Hello.java」のルートパネルに配置されます。事実、AJAX With Easeアプリケーションはロジック部の機能をHelloCSS、HelloRPC、HelloHistoryの各ウィジェットにカプセル化しています。
カスケーディングスタイルシート
GWTの大きな特徴は、カスケーディングスタイルシートを実際に採り入れていることです。すべてのウィジェットおよびパネルは、自由に変更できるデフォルトのCSSスタイルを持っています(例えば、gwt-Button{}を使った装飾可能なボタンウィジェットなど)。またaddStyleName(String)メソッドおよびremoveStyleName(String)メソッドを使ってGWTのJavaコードに独自のスタイルを追加したり削除することもできます。こうしたスタイルを.cssファイルに定義しておき、HTMLホストページでHTMLタグ<link>を使ってこれらを参照します。
以下に、「ajaxwithease.css」ファイルの内容を示します。このファイルには、先ほど示したHelloCSSコンポジットのボタンに利用されていたAJAX With Easeアプリケーション固有のawe-buttonスタイルが含まれています。
...
.gwt-CheckBox {
font-size: smaller;
}
...
.awe-button
{
color:#0000FF;
font-family:'trebuchet ms',helvetica,sans-serif;
font-size:84%;
font-weight:bold;
background-color:#fed;
}
...
この「ajaxwithease.css」ファイルには、GWTのデフォルトのスタイルも含まれています。というのも、奇妙なことに「applicationCreator.cmd」ファイルはGWTのデフォルトスタイルを含む.cssファイルを作成しないためです。
これでクライアント(ブラウザ+HTML/JavaScript)のほうは一段落したので、次はWebサーバーと通信してデータを取得し、ユーザーイベントに応答する必要があります。かつてのサーブレット/JSP開発では、この処理はサーバーとのやりとりを行ってページ全体をリロードすることを意味していました。AJAXの最大の利点はそうしたページ全体のリロードが必要なく、GWTのRPC基盤によってサーバーとの通信が容易になることです。
