
预计时间:300 分钟
本动手实验室假定您拥有以下技术的基本知识或者具备相关编程经验:
在开始之前,您需要在您的计算机上安装以下软件。GWT Netbeans IDE 插件已经包含在动手实验室压缩文件中。GWT NetBeans IDE 插件此时仍处于初期,但它提供了够好的模板来使用 NetBeans IDE 构建并运行 GWT 应用程序。越来越多的功能正加到该插件中来。当新插件可用时,本动手实验室将随之更新。
在本练习中,您将把 GWT NetBeans 插件安装到 NetBeans IDE 中。


在本练习中,您将使用 NetBeans 构建一个简单的 HelloWorld GWT 应用程序。您将把 Google Web 工具包安装路径配置到 NetBeans IDE 中,这只需操作一次。
0.如果没有启动 NetBeans IDE 则启动它。0.如果您还没有启动 NetBeans IDE 请启动它。
1.创建一个 GWT NetBeans 项目。

图 1.10:创建一个新 Web 应用程序项目



图 1.12:GWTApplication 项目

图 1.13.第一个页面

图 1.14:显示结果
| /* * MainEntryPoint.java * * Created on May 18, 2007, 5:31 PM * * To change this template, choose Tools | Template Manager * and open the template in the editor. */ package org.yournamehere.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; /** * * @author sang */ public class MainEntryPoint implements EntryPoint { /** Creates a new instance of MainEntryPoint */ public MainEntryPoint() { } /** * The entry point method, called automatically by loading a module * that declares an implementing class as an entry-point */ public void onModuleLoad() { final Label label = new Label("Hello, GWT!!!"); final Button button = new Button("Click me!"); button.addClickListener(new ClickListener(){ public void onClick(Widget w) { label.setVisible(!label.isVisible()); } }); RootPanel.get().add(button); RootPanel.get().add(label); } } |
| package org.yournamehere.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; /** * * @author sang */ public class MainEntryPoint implements EntryPoint { /** Creates a new instance of MainEntryPoint */ public MainEntryPoint() { } /** * The entry point method, called automatically by loading a module * that declares an implementing class as an entry-point */ public void onModuleLoad() { final Label label = new Label("Hello, GWT!!!"); final Button button = new Button("Click me!"); button.addClickListener(new ClickListener(){ public void onClick(Widget w) { label.setVisible(!label.isVisible()); } }); Button button2 = new Button("I am the 2nd button. Click me!"); button2.addClickListener(new ClickListener(){ public void onClick(Widget w) { Window.alert("Life is worth living.. with Passion!"); } }); RootPanel.get().add(button); RootPanel.get().add(button2); RootPanel.get().add(label); } } |










在本练习中,您学习了如何使用 NetBeans 构建并运行一个 HelloWorld GWT 应用程序。
在本练习中,您将使用 NetBeans IDE 构建两个示例应用程序 —— “Hello”以及 “Kitchen Sink”。两个应用程序都随附在 GWT
包中。它们同使用 GWT 包随附的命令行 shell 命令运行和生成的程序是同样的应用程序。您必须首先完成练习 1,因而 NetBeans IDE 中 GWT 的位置被正确地配置。
在本步骤中,您将使用 NetBeans 构建并运行 “Hello”示例应用程序。在动手实验室的压缩文件中,已提供了该应用程序,是名为 GWTHello 的“可供生成”的 NetBeans 项目。此应用程序同练习 1 中您构建的 GWTApplication 运行起来完全一样。
0.如果您还没有启动 NetBeans IDE 请启动它。
1.打开 GWTHello NetBeans
项目。

图 2.10: 打开 GWTHello NetBeans 项目

| /* * Copyright 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.sample.hello.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; public class Hello implements EntryPoint { public void onModuleLoad() { Button b = new Button("Click me", new ClickListener() { public void onClick(Widget sender) { Window.alert("Hello, AJAX"); } }); RootPanel.get().add(b); // Create a new button along with event listener. // The event listener has listener method called onClick(). Button c = new Button("Click me 2", new ClickListener() { public void onClick(Widget sender) { Window.alert("Hello, AJAX2"); } }); RootPanel.get().add(c); } } |

在本步骤中,您将使用 NetBeans 构建并运行“Kitchen Sink”示例应用程序,然后修改Buttons.java 以添加您自己的按钮。在动手实验室的压缩文件中,已提供了该应用程序,是名为 GWTKitchenSink 的“可供生成”的 NetBeans 项目
0.如果您还没有启动 NetBeans IDE 请启动它。
1.打开 GWTKitchenSink NetBeans
项目。
2.如果您遇到引用问题先解决引用(如上面所述)。
3.生成并运行 GWTKitchenSink 项目。



| /* * Copyright 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.sample.kitchensink.client; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.RadioButton; import com.google.gwt.user.client.ui.VerticalPanel; /** * Demonstrates the various button widgets. */ public class Buttons extends Sink { public static SinkInfo init() { return new SinkInfo("Buttons", "GWT supports all the myriad types of buttons that exist in HTML. " + "Here are a few for your viewing pleasure.") { public Sink createInstance() { return new Buttons(); } }; } // Create button and checkbox objects private Button disabledButton = new Button("Disabled Button"); private CheckBox disabledCheck = new CheckBox("Disabled Check"); private Button normalButton = new Button("Normal Button"); private Button myOwnButton = new Button("My Own Button"); private CheckBox normalCheck = new CheckBox("Normal Check"); // Create a vertical panel private VerticalPanel panel = new VerticalPanel(); // Create radio buttons private RadioButton radio0 = new RadioButton("group0", "Choice 0"); private RadioButton radio1 = new RadioButton("group0", "Choice 1"); private RadioButton radio2 = new RadioButton("group0", "Choice 2 (Disabled)"); private RadioButton radio3 = new RadioButton("group0", "Choice 3"); private RadioButton radio4 = new RadioButton("group0", "Choice 4"); // Constructor of the Buttons class public Buttons() { HorizontalPanel hp; // Create a horizontal panel object and add buttons to it. // Also add the horizontal panel object to the vertical panel. panel.add(hp = new HorizontalPanel()); hp.setSpacing(8); hp.add(normalButton); hp.add(disabledButton); hp.add(myOwnButton); // Create a horizontal panel object and add checkboxes to it. // Also add the horizontal panel object to the vertical panel. panel.add(hp = new HorizontalPanel()); hp.setSpacing(8); hp.add(normalCheck); hp.add(disabledCheck); // Create a horizontal panel object and add radion buttons to it. // Also add the horizontal panel object to the vertical panel. panel.add(hp = new HorizontalPanel()); hp.setSpacing(8); hp.add(radio0); hp.add(radio1); hp.add(radio2); hp.add(radio3); hp.add(radio4); // Set the disabled flags to widget objects disabledButton.setEnabled(false); disabledCheck.setEnabled(false); radio2.setEnabled(false); panel.setSpacing(8); setWidget(panel); } public void onShow() { } } |

| /* * Copyright 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.sample.kitchensink.client; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.RadioButton; import com.google.gwt.user.client.ui.VerticalPanel; /** * Demonstrates the various button widgets. */ public class Buttons extends Sink { public static SinkInfo init() { return new SinkInfo("Buttons", "GWT supports all the myriad types of buttons that exist in HTML. " + "Here are a few for your viewing pleasure.") { public Sink createInstance() { return new Buttons(); } }; } // Create button and checkbox objects private Button disabledButton = new Button("Disabled Button"); private CheckBox disabledCheck = new CheckBox("Disabled Check"); private Button normalButton = new Button("Normal Button"); private Button myOwnButton = new Button("My Own Button"); private CheckBox normalCheck = new CheckBox("Normal Check"); // Create a vertical panel private VerticalPanel panel = new VerticalPanel(); // Create radio buttons private RadioButton radio0 = new RadioButton("group0", "Choice 0"); private RadioButton radio1 = new RadioButton("group0", "Choice 1"); private RadioButton radio2 = new RadioButton("group0", "Choice 2 (Disabled)"); private RadioButton radio3 = new RadioButton("group0", "Choice 3"); private RadioButton radio4 = new RadioButton("group0", "Choice 4"); // Constructor of the Buttons class public Buttons() { HorizontalPanel hp; // Create a horizontal panel object and add buttons to it. // Also add the horizontal panel object to the vertical panel. panel.add(hp = new HorizontalPanel()); hp.setSpacing(8); hp.add(normalButton); hp.add(disabledButton); hp.add(myOwnButton); // Create a horizontal panel object and add checkboxes to it. // Also add the horizontal panel object to the vertical panel. panel.add(hp = new HorizontalPanel()); hp.setSpacing(8); hp.add(normalCheck); hp.add(disabledCheck); // Create a horizontal panel object and add radion buttons to it. // Also add the horizontal panel object to the vertical panel. panel.add(hp = new HorizontalPanel()); hp.setSpacing(8); hp.add(radio0); hp.add(radio1); hp.add(radio2); hp.add(radio3); hp.add(radio4); // Add my own panel panel.add(hp = new HorizontalPanel()); hp.setSpacing(8); hp.add(normalButton); hp.add(normalCheck); hp.add(radio0); // Set the disabled flags to widget objects disabledButton.setEnabled(false); disabledCheck.setEnabled(false); radio2.setEnabled(false); panel.setSpacing(8); setWidget(panel); } public void onShow() { } } |

| /* * Copyright 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.sample.kitchensink.client; import com.google.gwt.user.client.Command; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.MenuBar; import com.google.gwt.user.client.ui.MenuItem; /** * Demonstrates {@link com.google.gwt.user.client.ui.MenuBar} and * {@link com.google.gwt.user.client.ui.MenuItem}. */ public class Menus extends Sink implements Command { public static SinkInfo init() { return new SinkInfo("Menus", "The GWT <code>MenuBar</code> class makes it easy to build menus, " + "including cascading sub-menus.") { public Sink createInstance() { return new Menus(); } }; } // Create empty master MenuBar object private MenuBar menu = new MenuBar(); public Menus() { // Create a sub-sub-menu bar and add items to the sub-sub-menu bar MenuBar subMenu = new MenuBar(true); subMenu.addItem("<code>Code</code>", true, this); subMenu.addItem("<strike>Strikethrough</strike>", true, this); subMenu.addItem("<u>Underlined</u>", true, this); // Create a new sub-menu bar and add items to it MenuBar menu0 = new MenuBar(true); menu0.addItem("<b>Bold</b>", true, this); menu0.addItem("<i>Italicized</i>", true, this); menu0.addItem("More »", true, subMenu); // Create a new sub-menu bar and add items to it MenuBar menu1 = new MenuBar(true); menu1.addItem("<font color='#FF0000'><b>Apple</b></font>", true, this); menu1.addItem("<font color='#FFFF00'><b>Banana</b></font>", true, this); menu1.addItem("<font color='#FFFFFF'><b>Coconut</b></font>", true, this); menu1.addItem("<font color='#8B4513'><b>Donut</b></font>", true, this); // Create a new sub-menu bar and add items to it MenuBar menu2 = new MenuBar(true); menu2.addItem("Bling", this); menu2.addItem("Ginormous", this); menu2.addItem("<code>w00t!</code>", true, this); // Create a new sub-menu bar and add items to it MenuBar menu3 = new MenuBar(true); menu3.addItem("Life is good!", this); menu3.addItem("Life is OK!", this); menu3.addItem("Life sucks!", this); // Add sub-menu bar's to the master menu bar menu.addItem(new MenuItem("Style", menu0)); menu.addItem(new MenuItem("Fruit", menu1)); menu.addItem(new MenuItem("Term", menu2)); menu.addItem(new MenuItem("Life", menu3)); menu.setWidth("100%"); setWidget(menu); } public void execute() { Window.alert("Thank you for selecting a menu item."); } public void onShow() { } } |

| private static Proto[]
fProto = new Proto[]{ new Proto("Beethoven", new Proto[]{ new Proto("Concertos", new Proto[]{ new Proto("No. 1 - C"), new Proto("No. 2 - B-Flat Major"), new Proto("No. 3 - C Minor"), new Proto("No. 4 - G Major"), new Proto("No. 5 - E-Flat Major"),}), new Proto("Quartets", new Proto[]{ new Proto("Six String Quartets"), new Proto("Three String Quartets"), new Proto("Grosse Fugue for String Quartets"),}), new Proto("Sonatas", new Proto[]{ new Proto("Sonata in A Minor"), new Proto("Sonata in F Major"),}), new Proto("Symphonies", new Proto[]{ new Proto("No. 1 - C Major"), new Proto("No. 2 - D Major"), new Proto("No. 3 - E-Flat Major"), new Proto("No. 4 - B-Flat Major"), new Proto("No. 5 - C Minor"), new Proto("No. 6 - F Major"), new Proto("No. 7 - A Major"), new Proto("No. 8 - F Major"), new Proto("No. 9 - D Minor"),}),}), new Proto("Sang Shin", new Proto[]{ new Proto("Rock and Roll", new Proto[]{ new Proto("Love me tender"), new Proto("Let it Be"), new Proto("Hey Jude"),}), new Proto("Country music", new Proto[]{ new Proto("Lost Highway"), new Proto("Six Days on the Road"), new Proto("Wide Open Road"),}), new Proto("Tango", new Proto[]{ new Proto("Jealousy"), new Proto("Tango of Roses"),}), new Proto("Hip Hop", new Proto[]{ new Proto("No. 1 - C Major"), new Proto("No. 2 - D Major"), new Proto("No. 9 - D Minor"),}),}), new Proto("Brahms", new Proto[]{ new Proto("Concertos", new Proto[]{ new Proto("Violin Concerto"), new Proto("Double Concerto - A Minor"), new Proto("Piano Concerto No. 1 - D Minor"), new Proto("Piano Concerto No. 2 - B-Flat Major"),}), new Proto("Quartets", new Proto[]{ new Proto("Piano Quartet No. 1 - G Minor"), new Proto("Piano Quartet No. 2 - A Major"), new Proto("Piano Quartet No. 3 - C Minor"), new Proto("String Quartet No. 3 - B-Flat Minor"),}), new Proto("Sonatas", new Proto[]{ new Proto("Two Sonatas for Clarinet - F Minor"), new Proto("Two Sonatas for Clarinet - E-Flat Major"),}), new Proto("Symphonies", new Proto[]{ new Proto("No. 1 - C Minor"), new Proto("No. 2 - D Minor"), new Proto("No. 3 - F Major"), new Proto("No. 4 - E Minor"),}),}), new Proto("Mozart", new Proto[]{new Proto("Concertos", new Proto[]{ new Proto("Piano Concerto No. 12"), new Proto("Piano Concerto No. 17"), new Proto("Clarinet Concerto"), new Proto("Violin Concerto No. 5"), new Proto("Violin Concerto No. 4"),}),}),}; |


| .ks-List .ks-SinkItem-selected { background-color: #C3D9FF; } /* -------------- This is my own ------ */ .ks-List .ks-SinkItem-selected-myown { background-color: #EEFFEE; font-weight: bold; font-style: italic; } |
| public void
setSinkSelection(String name) { if (selectedSink != -1) list.getWidget(selectedSink).removeStyleName("ks-SinkItem-selected-myown"); for (int i = 0; i < sinks.size(); ++i) { SinkInfo info = (SinkInfo) sinks.get(i); if (info.getName().equals(name)) { selectedSink = i; list.getWidget(selectedSink).addStyleName("ks-SinkItem-selected-myown"); return; } } } |




| package my.company.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.ui.CheckBox; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; /** * * @author sang */ public class MainEntryPoint implements EntryPoint { /** Creates a new instance of MainEntryPoint */ public MainEntryPoint() { } /** * A composite of a TextBox and a CheckBox that optionally enables it. */ public static class OptionalTextBox extends Composite implements ClickListener { private TextBox textBox = new TextBox(); private CheckBox checkBox = new CheckBox(); /** * Constructs an OptionalTextBox with the given caption on the check. * * @param caption the caption to be displayed with the check box */ public OptionalTextBox(String caption) { // Place the check above the text box using a vertical panel. VerticalPanel panel = new VerticalPanel(); panel.add(checkBox); panel.add(textBox); // Set the check box's caption, and check it by default. checkBox.setText(caption); checkBox.setChecked(true); checkBox.addClickListener(this); // All composites must call initWidget() in their constructors. initWidget(panel); // Give the overall composite a style name. setStyleName("example-OptionalCheckBox"); } public void onClick(Widget sender) { if (sender == checkBox) { // When the check box is clicked, update the text box's enabled state. textBox.setEnabled(checkBox.isChecked()); } } /** * Sets the caption associated with the check box. * * @param caption the check box's caption */ public void setCaption(String caption) { // Note how we use the use composition of the contained widgets to provide // only the methods that we want to. checkBox.setText(caption); } /** * Gets the caption associated with the check box. * * @return the check box's caption */ public String getCaption() { return checkBox.getText(); } } public void onModuleLoad() { // Create an optional text box and add it to the root panel. OptionalTextBox otb = new OptionalTextBox("Check this to enable me"); RootPanel.get().add(otb); } } |







| package my.company.client; import com.google.gwt.user.client.rpc.RemoteService; // Service interface, which has a single method called myMethod. public interface GWTService extends RemoteService{ public String myMethod(String s); } |
| package my.company.client; import com.google.gwt.user.client.rpc.AsyncCallback; // Asynchronous Service interface. Note that a AsynchCallBack // object needs to be passed as a parameter. public interface GWTServiceAsync { public void myMethod(String s, AsyncCallback callback); } |
| package my.company.server; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import my.company.client.GWTService; // Service implementation, which provides the implementation of // GWTService service interface. public class GWTServiceImpl extends RemoteServiceServlet implements GWTService { public String myMethod(String s) { // Do something interesting with 's' here on the server. return "Server says: " + s; } } |
| package my.company.client; import com.google.gwt.core.client.GWT; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.rpc.ServiceDefTarget; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; public class GWTServiceUsageExample extends VerticalPanel { private Label lblServerReply = new Label(); private TextBox txtUserInput = new TextBox(); private Button btnSend = new Button("Send to server"); public GWTServiceUsageExample() { add(new Label("Input your text: ")); add(txtUserInput); add(btnSend); add(lblServerReply); // Create an asynchronous callback to handle the result. // The AynchCallBack object has to provide implementation // of onSuccess() and onFailure() metods. final AsyncCallback callback = new AsyncCallback() { public void onSuccess(Object result) { lblServerReply.setText((String)result); } public void onFailure(Throwable caught) { lblServerReply.setText("Communication failed"); } }; // Listen for the button clicks. When "Send to server" // button is pressed, the RPC operation occurs. btnSend.addClickListener(new ClickListener(){ public void onClick(Widget w) { // Make remote call. Control flow will continue immediately and later // 'callback' will be invoked when the RPC completes. getService().myMethod(txtUserInput.getText(), callback); } }); } public static GWTServiceAsync getService(){ // Create the client proxy. Note that although you are creating the // service interface proper, you cast the result to the asynchronous // version of // the interface. The cast is always safe because the generated proxy // implements the asynchronous interface automatically. GWTServiceAsync service = (GWTServiceAsync) GWT.create(GWTService.class); // Specify the URL at which our service implementation is running. // Note that the target URL must reside on the same domain and port from // which the host page was served. // ServiceDefTarget endpoint = (ServiceDefTarget) service; String moduleRelativeURL = GWT.getModuleBaseURL() + "gwtservice"; endpoint.setServiceEntryPoint(moduleRelativeURL); return service; } } |
| <?xml version="1.0"
encoding="UTF-8"?> <web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <servlet> <servlet-name>GWTService</servlet-name> <servlet-class>my.company.server.GWTServiceImpl</servlet-class> </servlet> <servlet-mapping> <servlet-name>GWTService</servlet-name> <url-pattern>/my.company.Main/gwtservice</url-pattern> </servlet-mapping> <session-config> <session-timeout> 30 </session-timeout> </session-config> <welcome-file-list> <welcome-file> index.jsp </welcome-file> </welcome-file-list> </web-app> |
| package my.company.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; /** * * @author sang */ public class MainEntryPoint implements EntryPoint { /** Creates a new instance of MainEntryPoint */ public MainEntryPoint() { } /** * The entry point method, called automatically by loading a module * that declares an implementing class as an entry-point */ public void onModuleLoad() { final Label label = new Label("Hello, GWT!!!"); final Button button = new Button("Click me!"); // The GWTServiceUsageExample is a VerticalPanel object, the constructor of // which performs RPC operation with the server. GWTServiceUsageExample rpcCallingPanel = new GWTServiceUsageExample(); button.addClickListener(new ClickListener(){ public void onClick(Widget w) { label.setVisible(!label.isVisible()); } }); RootPanel.get().add(button); RootPanel.get().add(label); // Add the GWTServiceUsageExample to the panel // so that you can test it. RootPanel.get().add(rpcCallingPanel); } } |










在本练习中,您将要使用 NetBeans IDE 构建并运行随附于 Google Web 工具包的“Dynamic Table”示例应用程序。此示例应用程序使用 GWT 的远程过程调用(RPC)功能。它也将创建并使用自定义部件。
0.如果您还没有启动 NetBeans IDE 请启动它。
1. 打开 GWTDynaTable 项目。
2. 如果您遇到引用问题则解决引用(如 上面所述)。
3. 运行 GWTDynaTable
项目..

图 5.10:“Dynamic Table” 示例应用程序的运行结果
| /* * Copyright 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.sample.dynatable.client; import com.google.gwt.user.client.rpc.RemoteService; // Service interface. It has one method called getPeople. public interface SchoolCalendarService extends RemoteService { Person[] getPeople(int startIndex, int maxCount); } |
| /* * Copyright 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.sample.dynatable.client; import com.google.gwt.user.client.rpc.AsyncCallback; // Asynchronous service interface. It has AsyncCallback object as a parameter. public interface SchoolCalendarServiceAsync { void getPeople(int startIndex, int maxCount, AsyncCallback callback); } |
| /* * Copyright 2006 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.google.gwt.sample.dynatable.server; import com.google.gwt.sample.dynatable.client.Person; import com.google.gwt.sample.dynatable.client.Professor; import com.google.gwt.sample.dynatable.client.Schedule; import com.google.gwt.sample.dynatable.client.SchoolCalendarService; import com.google.gwt.sample.dynatable.client.Student; import com.google.gwt.sample.dynatable.client.TimeSlot; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Random; // This is service implementation on the server side. The service implementation // has to extends "RemoteServiceServlet" class and implements service interface. public class SchoolCalendarServiceImpl extends RemoteServiceServlet implements SchoolCalendarService { private static final String[] FIRST_NAMES = new String[]{ "Inman", "Sally", "Omar", "Teddy", "Jimmy", "Cathy", "Barney", "Fred", "Eddie", "Carlos"}; private static final String[] LAST_NAMES = new String[]{ "Smith", "Jones", "Epps", "Gibbs", "Webber", "Blum", "Mendez", "Crutcher", "Needler", "Wilson", "Chase", "Edelstein"}; private static final String[] SUBJECTS = new String[]{ "Chemistry", "Phrenology", "Geometry", "Underwater Basket Weaving", "Basketball", "Computer Science", "Statistics", "Materials Engineering", "English Literature", "Geology"}; private static final Person[] NO_PEOPLE = new Person[0]; public SchoolCalendarServiceImpl() { generateRandomPeople(); } // This method implements a method defined in the service interface. // This method returns an array of Person objects. public Person[] getPeople(int startIndex, int maxCount) { int peopleCount = people.size(); int start = startIndex; if (start >= peopleCount) { return NO_PEOPLE; } int end = Math.min(startIndex + maxCount, peopleCount); if (start == end) { return NO_PEOPLE; } int resultCount = end - start; Person[] results = new Person[resultCount]; for (int from = start, to = 0; to < resultCount; ++from, ++to) { results[to] = (Person) people.get(from); } return results; } private void generateRandomPeople() { for (int i = 0; i < MAX_PEOPLE; ++i) { Person person = generateRandomPerson(); people.add(person); } } private Person generateRandomPerson() { // 1 out of every so many people is a prof. // if (rnd.nextInt(STUDENTS_PER_PROF) == 1) { return generateRandomProfessor(); } else { return generateRandomStudent(); } } private Person generateRandomProfessor() { Professor prof = new Professor(); String firstName = pickRandomString(FIRST_NAMES); String lastName = pickRandomString(LAST_NAMES); prof.setName("Dr. " + firstName + " " + lastName); String subject = pickRandomString(SUBJECTS); prof.setDescription("Professor of " + subject); generateRandomSchedule(prof.getTeachingSchedule()); return prof; } private void generateRandomSchedule(Schedule sched) { int range = MAX_SCHED_ENTRIES - MIN_SCHED_ENTRIES + 1; int howMany = MIN_SCHED_ENTRIES + rnd.nextInt(range); TimeSlot[] timeSlots = new TimeSlot[howMany]; for (int i = 0; i < howMany; ++i) { int startHrs = 8 + rnd.nextInt(9); // 8 am - 5 pm int startMins = 15 * rnd.nextInt(4); // on the hour or some quarter int dayOfWeek = 1 + rnd.nextInt(5); // Mon - Fri int absStartMins = 60 * startHrs + startMins; // convert to minutes int absStopMins = absStartMins + CLASS_LENGTH_MINS; timeSlots[i] = new TimeSlot(dayOfWeek, absStartMins, absStopMins); } Arrays.sort(timeSlots); for (int i = 0; i < howMany; ++i) { sched.addTimeSlot(timeSlots[i]); } } private Person generateRandomStudent() { Student student = new Student(); String firstName = pickRandomString(FIRST_NAMES); String lastName = pickRandomString(LAST_NAMES); student.setName(firstName + " " + lastName); String subject = pickRandomString(SUBJECTS); student.setDescription("Majoring in " + subject); generateRandomSchedule(student.getClassSchedule()); return student; } private String pickRandomString(String[] a) { int i = rnd.nextInt(a.length); return a[i]; } /** * Write the serialized response out to stdout. This is a very unusual thing * to do, but it allows us to create a static file version of the response * without deploying a servlet. */ protected void onAfterResponseSerialized(String serializedResponse) { System.out.println(serializedResponse); } private final List people = new ArrayList(); private final Random rnd = new Random(3); private static final int CLASS_LENGTH_MINS = 50; private static final int MAX_SCHED_ENTRIES = 5; private static final int MIN_SCHED_ENTRIES = 1; private static final int MAX_PEOPLE = 100; private static final int STUDENTS_PER_PROF = 5; } |



在本练习中,您将构建并运行随附在 Google Web Toolkit 包中的 “JSON” 示例应用程序。本示例应用程序使用 JSON 作为浏览器和服务器之间的数据格式。
0.如果您还没有启动 NetBeans IDE 请启动它。
1. 打开 GWTJSON 项目。
2. 如果您遇到引用问题则解决引用(如 上面所述)。
3.生成并运行 GWTJSON
项目。

图 6.10:“JSON” 示例应用程序的运行结果
4. 注意到数据以 JSON 的形式从服务器端取到并以树的形式显示。(如下图 6.11 所示)

图 6.11: 数据以 JSON 的形式取到并以树的形式显示。

在本练习中,您将构建并运行随附在 Google Web Toolkit 包中的 “GWTMail” 示例应用程序。
0.如果您还没有启动 NetBeans IDE 请启动它。
1. 打开 GWTMail 项目
2.如果您遇到引用问题则解决引用(如 上面所述)。
3. 构建并运行 GWTMail
项目

图 7.10:“GWTMail” 示例应用程序的运行结果


在本练习中,您将构建并运行随附在 Google Web Toolkit 包中的 “GWTSimpleXML” 示例应用程序。
0.如果您还没有启动 NetBeans IDE 请启动它。
1. 打开 GWTSimpleXML 项目
2. 如果您遇到引用问题则解决引用(如 上面所述)。
3.生成并运行 GWTSimpleXML
项目


0.如果您还没有启动 NetBeans IDE 请启动它。
1. 打开 GWTHistoryExample 项目
2.如果您遇到引用问题则解决引用(如 上面所述)。
3.生成并运行 GWTHistoryExample
project


| package
com.google.gwt.sample.hello.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; public class Hello implements EntryPoint { public void onModuleLoad() { Button b = new Button("Click me", new ClickListener() { public void onClick(Widget sender) { // Window.alert("Hello, AJAX"); myalert("Hello, AJAX using Native JavaScript"); } }); RootPanel.get().add(b); } // // Add native JavaScript code. // public static native void myalert(String msg) /*-{ $wnd.alert(msg); }-*/; } |
3.生成并运行 GWTHelloNativeJavaScript
项目




| package
com.google.gwt.sample.hello.client; import com.google.gwt.core.client.EntryPoint; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.ClickListener; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.Widget; public class Hello implements EntryPoint { public void onModuleLoad() { Button b = new Button("Click me", new ClickListener() { public void onClick(Widget sender) { // Window.alert("Hello, AJAX"); // myalert("Hello, AJAX using Native JavaScript"); bar(new Hello(), "Message sent to the bar native method from Java method"); } }); RootPanel.get().add(b); } // Add native JavaScript code. public static native void myalert(String msg) /*-{ $wnd.alert(msg); }-*/; // Instance and static fields which will be accessed from JavaScript code String myInstanceField = "Life is worth living with Passion!"; static String myStaticField; // Instance method void instanceFoo(String s) { myalert(s); } // Static method static void staticFoo(String s) { myalert(s); } // Native method in which Java methods and fields are accessed from the // JavaScript code. // public native void bar(Hello x, String s) /*-{ // Call instance method instanceFoo() on this this.@com.google.gwt.sample.hello.client.Hello::instanceFoo(Ljava/lang/String;)("The 1st " + s); // Call instance method instanceFoo() on x x.@com.google.gwt.sample.hello.client.Hello::instanceFoo(Ljava/lang/String;)("The 2nd " + s); // Call static method staticFoo() @com.google.gwt.sample.hello.client.Hello::staticFoo(Ljava/lang/String;)("The 3rd " + s); // Read instance field on this var val = this.@com.google.gwt.sample.hello.client.Hello::myInstanceField; @com.google.gwt.sample.hello.client.Hello::staticFoo(Ljava/lang/String;)("Instance field contains " + val); // Write instance field on x and read it again x.@com.google.gwt.sample.hello.client.Hello::myInstanceField = val + " Really!"; var val2 = x.@com.google.gwt.sample.hello.client.Hello::myInstanceField; @com.google.gwt.sample.hello.client.Hello::staticFoo(Ljava/lang/String;)("Instance field contains " + val2); // Write static field (no qualifier) and read it again @com.google.gwt.sample.hello.client.Hello::myStaticField = "Message from static field"; var val3 = @com.google.gwt.sample.hello.client.Hello::myStaticField; @com.google.gwt.sample.hello.client.Hello::staticFoo(Ljava/lang/String;)("Static field contains " + val3); }-*/; } |






| public interface GWTService
extends RemoteService{ public String myMethod(String s); public int addNumber(int x, int y); } |
| public class
GWTServiceUsageExample extends VerticalPanel { private Label lblServerReply = new Label(); private Label lblAddReply = new Label(); private TextBox txtUserInput = new TextBox(); private TextBox txtXInput = new TextBox(); private TextBox txtYInput = new TextBox(); private Button btnSend = new Button("Send to server"); private Button btnAdd = new Button("Add x + y"); public GWTServiceUsageExample() { add(new Label("Input your text: ")); add(txtUserInput); add(btnSend); add(lblServerReply); add(new Label("Input x and y: ")); add(new Label("Input x: ")); add(txtXInput); add(new Label("Input y: ")); add(txtYInput); add(btnAdd); add(lblAddReply); // Create an asynchronous callback to handle the result. final AsyncCallback callback = new AsyncCallback() { public void onSuccess(Object result) { lblServerReply.setText((String)result); } public void onFailure(Throwable caught) { lblServerReply.setText("Communication failed"); } }; // Create an asynchronous callback to handle the result. // Add your code here // Listen for the button clicks btnSend.addClickListener(new ClickListener(){ public void onClick(Widget w) { // Make remote call. Control flow will continue immediately and later // 'callback' will be invoked when the RPC completes. getService().myMethod(txtUserInput.getText(), callback); } }); // Listen for the button clicks for addition btnAdd.addClickListener(new ClickListener(){ public void onClick(Widget w) { // Make remote call. Control flow will continue immediately and later // 'callback' will be invoked when the RPC completes. getService().addNumber(Integer.parseInt(txtXInput.getText()), Integer.parseInt(txtYInput.getText()),callbackAdd); } }); } public static GWTServiceAsync getService(){ // Create the client proxy. Note that although you are creating the // service interface proper, you cast the result to the asynchronous // version of // the interface. The cast is always safe because the generated proxy // implements the asynchronous interface automatically. GWTServiceAsync service = (GWTServiceAsync) GWT.create(GWTService.class); // Specify the URL at which our service implementation is running. // Note that the target URL must reside on the same domain and port from // which the host page was served. // ServiceDefTarget endpoint = (ServiceDefTarget) service; String moduleRelativeURL = GWT.getModuleBaseURL() + "gwtservice"; endpoint.setServiceEntryPoint(moduleRelativeURL); return service; } } |