<!----><!----><!---->
<!---->
实现客户端功能
我们的StockWatcher
例子到目前为止已经很好了,回顾一下,我们用GWT
的widgets和 panels
已经设计并实现了UI
,并且为用户实现了键盘单击事件
的初始化。现在,我们要为应用程序写客户端代码,让它实现功能。
验证用户输入
当用户第一次使用StockWatcher
,他需要通过在文本框里输入存货订单标示(
一次只能增加一条)
来向他的watch
list
中增加存货。然而在我们增加一条存货的时候,我们需要检验新输入是否有效,如果无效,我们需要通过一个对话框来警告他。
业务顺序的第一步是给addStock()
增加代码来完成创建存货。我们使用TextBox
widget
的getText()
方法来获得文本。GWT
的 widgets
和
panels
包含了丰富的属性和方法,很多都是和HTML DOM
元素相类似的。当我们转换用户在一个标准表单中的输入的时候,我们使用正则表达式来检查它的格式(
记住在java
和JavaScript
中使用正则表达式意思是一样的)
.
以下是更新后的addStock()
方法:
private void addStock() {
final String symbol = newSymbolTextBox.getText().toUpperCase().trim();
newSymbolTextBox.setFocus(true);
// symbol must be between 1 and 10 chars that
are numbers, letters, or //dots
if (!symbol.matches("^[0-9a-zA-Z\\.]{1,10}$"))
{
Window.alert("'" + symbol + "'
is not a valid symbol.");
newSymbolTextBox.selectAll();
return;
}
newSymbolTextBox.setText("");
// now we need to add the stock to the list...
}
由于调用了 Window.alert(String)
方法,
因此我们需要增加另一个import:
import
com.google.gwt.user.client.Window;
现在,轻松了许多,重编译并运行StockWatcher application
来测试输入验证。
如果你在hosted mode
下的浏览器
已经打开了,你不需要重启它。只需要点击工具栏上的
Refresh
按钮来重载你更新后的GWT
代码。
<!----><!---->
<!---->
操纵watch list
尽管StockWatcher
已经有了验证存货输入的能力,但它仍然没有实现它的功能:用户依然不能看到增加的存货。现在让我们来继续完成功能吧。回顾一下,我们的UI
包含了一个名为stocksFlexTable
的FlexTable
窗口,它用于包含watch list
。列表的每行都包含一个存货标识,当前价格,价格变动和一个用于移除存货的按钮。当前我们仅关注增加和移除存货功能,不用去担心设定价格和变更。
首先,
我们需要一个数据结构来保存当前可见的存货标识列表,我们使用标准的Java ArrayList
来调用我们的存货列表:
public class StockWatcher implements
EntryPoint {
private VerticalPanel mainPanel = new VerticalPanel();
private FlexTable stocksFlexTable = new FlexTable();
private HorizontalPanel addPanel = new HorizontalPanel();
private TextBox newSymbolTextBox = new TextBox();
private Button addButton = new Button("Add");
private Label lastUpdatedLabel = new Label();
private ArrayList<String> stocks = new
ArrayList<String>();
别忘记了新增的import:
import java.util.ArrayList;
接下来是有趣的部分。向addStock()
方法中增加如下的代码:
// don't add the stock if it's
already in the watch list
if (stocks.contains(symbol))
return;
// add the stock to the list
int row =
stocksFlexTable.getRowCount();
stocks.add(symbol);
stocksFlexTable.setText(row, 0,
symbol);
// add button to remove this stock
from the list
Button removeStock = new
Button("x");
removeStock.addClickListener(new
ClickListener(){
public void onClick(Widget sender) {
int removedIndex = stocks.indexOf(symbol);
stocks.remove(removedIndex);
stocksFlexTable.removeRow(removedIndex+1);
}
});
stocksFlexTable.setWidget(row, 3,
removeStock);
新条件应简单的关联。首先,通过给存货设定第一列的text
给我们的FlexTable
增加了新的一行,(
记住它的 setText(int,
int, String)
方法会自动创建你需要的新的单元格,所以我们不需要显示的设定表格大小)
。之后,我们创建了移除存货的按钮,并在指定ClickListener
从FlexTable
和ArrayList
中移除存货前使用setWidget(int,
int, Widget)
方法把它放在表格的最后一列。
现在的事实:运行或刷新hosted mode
下的浏览器。得救了,你可以随意的添加和移除存货信息。现在我们唯一没有实现的功能是存货的价格及其变更。
at will
意为随意
<!----><!---->
<!---->
刷新存货价格
StockWatcher
最后且最重要的功能是更新我们关心的存货价格。如果我们用传统的web
开发技术写应用程序的话,我们想更新价格需要每次都整个页面重载来响应。这可以用手或自动刷新(比如在HTML
头部使用<meta http-equiv="refresh"
content="5">
标签)来实现。在web2.0
中这是不够的,那些追捧崇拜的商人需要立马更新更新它们的存货价格,而不是烦人的页面刷新。
幸运的是,百忙中GWT
让更新你的应用程序内容变得很容易。让我们使用Timer
类来给StockWatcher
增加自动更新存货价格的功能。
使用定时器自动刷新
Timer
是单线程,浏览器安全的定时器类,它允许我们在未来某时安排代码运行
,或者使用scheduleRepeating(int)
或用scheduleRepeating(int)
重复。我们使用后面的方法每隔5
秒来自动更新我们的存货价格。
为了使用Timer
我们在我们的onModuleLoad()
方法中创建了一个新的实例并重写了run()
方法。当定时器工作的时候run()
方法将被调用。在我们的例子中,我们要调用一个将被写的名为refreshWatchList()
的方法来实际进行更新操作。给Timer
增加import
,之后如下修改onModuleLoad()
尾部的尾部:
Add the import for Timer
and
then modify the end of the end of the onModuleLoad() method as follows:
import
com.google.gwt.user.client.Timer;
public void onModuleLoad() {
...
// add the main panel to the HTML element with the id
"stockList"
RootPanel.get("stockList").add(mainPanel);
// setup timer to refresh list automatically
Timer refreshTimer = new Timer() {
public void run() {
refreshWatchList();
}
};
refreshTimer.scheduleRepeating(REFRESH_INTERVAL);
// move cursor focus to the text box
newSymbolTextBox.setFocus(true);
}
In addition to the change to onModuleLoad(), you'll
also need to define the constant that specifies the refresh rate. Add that to
the top of the StockWatcher class.
private static final int
REFRESH_INTERVAL = 5000; // ms
在我们继续之前,我们需要增加调用新的refreshWatchList()
方法不止一次。在我们增加新的存货到FlexTable
后我们将在addStock()
方法中立即调用它。(
所以新的存货会马上获得它的价格及变更情况):
private void addStock() {
...
Button removeStock = new Button("x");
removeStock.addClickListener(new ClickListener(){
public void onClick(Widget sender) {
int removedIndex =
stocks.indexOf(symbol);
stocks.remove(removedIndex);
stocksFlexTable.removeRow(removedIndex+1);
}
});
stocksFlexTable.setWidget(row, 3, removeStock);
// get stock price
refreshWatchList();
}
private void refreshWatchList() {
// Code will be added in the next section
}
StockPrice
类
GWT
中主要方式的一种就是在java
语言中允许我们传播AJAX
的开发。因此,我们可以采取静态类型检查和面向对象编程的嵌入时间(time-tested
)模式,可以和现代的IDE
特性结合,如代码补全和自动重构等,使得它以良好的代码管理为基础,比以往更加简单的去写健壮的AJAX
应用程序。
对于StockWatcher
来说,我们将存货价格数据放到它自己的类中进行重构。创建一个名为StockPrice
位于com.google.gwt.sample.stockwatcher.client
包下的java
类(in Eclipse, File -> New ->
Class
).
<!----><!---->
<!---->
以下是我们的新类的完整实现:
package
com.google.gwt.sample.stockwatcher.client;
public class StockPrice {
private String symbol;
private double price;
private double change;
public StockPrice() {
}
public StockPrice(String symbol, double price, double change) {
this.symbol = symbol;
this.price = price;
this.change = change;
}
public String getSymbol() {
return this.symbol;
}
public double getPrice() {
return this.price;
}
public double getChange() {
return this.change;
}
public double getChangePercent() {
return 10.0 * this.change / this.price;
}
public void setSymbol(String symbol) {
this.symbol = symbol;
}
public void setPrice(double price) {
this.price = price;
}
public void setChange(double change) {
this.change = change;
}
}
生成存货价格
既然我们有一个StockPrice
类来封装存货价格数据,让我们使用它来更新watch list
表格。首先,我们需要生成实际数据。作为从在线数据源中检索真实的存货价格实际数据的替代,我们使用GWT
内置的Random
类来创建伪随机价格并改变其值。我们将用这些值填充StockPrice
对象数组,之后传给它们另一个功能来更新watch list
FlexTable
。向我们的StockWatcher
类增加如下import
和函数:
import
com.google.gwt.user.client.Random;
private void refreshWatchList()
{
final double MAX_PRICE = 100.0; // $100.00
final double MAX_PRICE_CHANGE = 0.02; // +/- 2%
StockPrice[] prices = new StockPrice[stocks.size()];
for (int i=0; i<stocks.size(); i++) {
double price = Random.nextDouble() * MAX_PRICE;
double change = price * MAX_PRICE_CHANGE * (Random.nextDouble() * 2.0 -
1.0);
prices[i] = new StockPrice((String)stocks.get(i), price, change);
}
updateTable(prices);
}
更新watch list
最后的2
个新函数会更新新价格的显示。在updateTable(StockPrice)
方法中,你会发现例子中使用NumberFormat
来格式话数值为字符串。在我们的例子中,我们用它以货币形式来格式化价格,且价格变动之前显示一个指示符。相似的,注意在updateTable(StockPrice[])
方法中的使用DateTimeFormat
类来格式化当前日期时间。接下来把这些功能加到StockWatcher
中:
private void
updateTable(StockPrice[] prices) {
for (int i=0; i<prices.length; i++) {
updateTable(prices[i]);
}
// change the last update timestamp
lastUpdatedLabel.setText("Last update : " +
DateTimeFormat.getMediumDateTimeFormat().format(new
Date()));
}
private void updateTable(StockPrice
price) {
// make sure the stock is still in our watch list
if (!stocks.contains(price.getSymbol())) {
return;
}
int row = stocks.indexOf(price.getSymbol()) + 1;
// apply nice formatting to price and change
String priceText = NumberFormat.getFormat("#,##0.00").format(price.getPrice());
NumberFormat changeFormat = NumberFormat.getFormat("+#,##0.00;-#,##0.00");
String changeText = changeFormat.format(price.getChange());
String changePercentText = changeFormat.format(price.getChangePercent());
// update the watch list with the new values
stocksFlexTable.setText(row, 1, priceText);
stocksFlexTable.setText(row, 2, changeText +
" (" + changePercentText + "%)");
}
DateTimeFormat
和 NumberFormat
类位于独立的包中,因此你需要为它们增加另外的import
。就像一个java
的标准Date
类一样:
import com.google.gwt.i18n
.client.DateTimeFormat;
import com.google.gwt.i18n
.client.NumberFormat;
import java.util.Date;
你可能已经注意到DateTimeFormat
和 NumberFormat
位于com.google.gwt.i18
的子包中,看来它们是用来以某种方式来处理国际化问题。事实上它们也确实这么做的。当你格式化数组和日期的时候,二个类都自动的使用你的应用程序的locale
设定。随后我们会在Getting Started guide
中讨论更多localizing
and translating your GWT application
(国际化和GWT
应用程序的转换)
又到了测试我们的改变的时候了。运行或刷新应用程序在hosted mode
,试着增加某种存货到watch list
。现在,我们可以看到每个存货的当前价格和变动情况。如果你观察列表一段事件,你会发现那些值会随着底部的时间戳,每隔5
秒中改变一次。
<!----><!---->
<!---->
好吧,看起来像我们的StockWatcher
程序工作的很完美,不是吗?
离你离开的时间越来越远,
它证明了一个细微的bug
。如果你找到它(hint: it's visible in the screenshot above
).
在下部分中,我们会使用我们的java
调试技巧来调试它。
分享到:
相关推荐
3. **异步通信(RPC)**:GWT支持异步远程过程调用(RPC),使得客户端和服务器之间的通信更加高效和流畅,提高了用户体验。 4. **自动编译和部署**:GWT提供了开发服务器,可以在代码改变时自动编译并刷新浏览器,...
这一部分还将深入讨论GWT的客户端数据管理,包括使用 Gin 和 Guice 进行依赖注入,以及使用GWT的 Place 和 History 模式来实现导航。另外,你将学习到如何利用GWT的Ext GWT(GXT)或SmartGWT等第三方库增强应用的...
"GWT+Quickview+-+by+elephi[1].dong+.mht"文件可能是一个关于GWT快速预览功能的教程或演示,帮助开发者了解如何在GWT应用中实现快速查看和预览功能,提升用户体验。 "GWT快速开发.pdf"这本书籍或手册,旨在加速...
### ExtGWT、GWT与GXT初学教程:打造企业级富客户端Web应用 #### 构建初识:ExtGWT与GWT的协同工作 ExtGWT,作为GWT(Google Web Toolkit)的有力补充,旨在为Java开发者提供更为丰富、功能全面的组件库,从而构建...
GWT允许开发者使用Java语言编写客户端代码,然后通过编译器将其转换成JavaScript,可以在各种浏览器上运行。本教程将引导你了解如何在Eclipse环境中配置和使用GWT进行开发。 首先,为了在Eclipse中开发GWT应用,你...
2. **客户端-服务器通信**:GWT提供了异步的RequestFactory和RPC机制,用于在客户端和服务器之间进行数据交换,实现高效且安全的通信。 3. **UI构建**:GWT提供了丰富的Widget库,包括按钮、表格、布局管理器等,...
6. **异步通信(GWT RPC)**:GWT提供了Remote Procedure Call (RPC)机制,使得客户端和服务器端可以进行高效的异步数据交换,这是GWT实现MVC模式的关键部分。 **进阶篇:深入GWT技术** 1. **模块化**:了解GWT模块...
总的来说,GWT in Practice教程提供了一个全面的视角,帮助读者理解GWT的背景、功能和实际应用,是初学者踏入GWT世界的好起点。通过学习,开发者可以充分利用Java的强类型和丰富的库,创建出高性能、易于维护的Web...
**GWT 入门教程与实例解析** Google Web Toolkit(GWT)是Google推出的一款用于构建高性能、跨浏览器的Web应用程序的开源开发工具。它基于Java语言,通过编译Java源代码为JavaScript,使得开发者可以利用Java的强大...
总结来说,"gwt服务器端(内含配置教程)"指的是如何在Eclipse中配置和开发GWT应用,包括服务器端的设置和与客户端的交互。通过学习和实践这个主题,开发者可以掌握使用Java开发高效、跨平台的Web应用的技能。
通常,这样的设计可能涉及到如何优雅地组织GWT代码结构、实现可重用的组件或遵循特定的设计原则,如MVP(Model-View-Presenter)模式,用于分离视图逻辑和业务逻辑。 标签“源码”和“工具”表明这篇博客可能探讨了...
标题 "Ext-Gwt(GWT)开发实例(整合Spring +Hibernate)" 涉及到的是一个实际项目开发的教程,其中结合了三个重要的技术框架:Google Web Toolkit (GWT),Spring 和 Hibernate。这个实例旨在展示如何在Web应用开发中...
3. **RPC与数据传输**:详细讲解如何使用GWT.RPC实现客户端和服务器的数据交互。 4. **优化技巧**:讨论如何通过代码分割、延迟加载和优化设置提升应用性能。 5. **调试与测试**:介绍GWT的开发模式和部署模式,以及...
GWT-Ext是一个基于Google Web Toolkit (GWT)的JavaScript库,它提供了丰富的用户界面组件和强大的数据绑定机制,使得...教程中的实例和练习将帮助你将理论知识转化为实践经验,为你的GWT-Ext开发之路打下坚实基础。
3. **GWT RPC与数据绑定**:讲解如何通过GWT的RPC机制实现客户端与服务器之间的通信,以及如何使用ValueProxy和DataProvider实现数据的远程加载和展示。 4. **GXT组件和主题**:详细介绍了GXT库中的组件,如Grid、...
4. **创建启用Ajax的服务**:GWT支持远程过程调用(RPC),允许客户端与服务器端的Java服务进行通信,实现数据的异步交换,增强用户体验。 5. **使用Geronimo构建和部署应用**:Geronimo作为应用服务器,提供了一个...
本教程集合了从入门到高级的全方位学习资源,包括PDF、PPT和Word格式的文档,覆盖了GWT的基础概念、核心组件、实际应用以及Ajax技术。 **一、GWT入门** 在入门阶段,首先需要理解GWT的基本概念,包括模块系统、事件...
- 通过使用SmartGWT,开发者可以利用Java编写客户端代码,然后自动编译为优化的JavaScript,实现跨浏览器兼容性。 2. **版本1.3的特点** - 在SmartGWT 1.3版本中,可能会包含一些新的特性、改进和修复的bug,具体...