處理客戶端的 Event
加入 Event Handler
在 GWT 中所使用的 event handler interface model 與其他的語言類似,要處理 Add 與 Remove 按鈕的 event,可以使用 ClickHandler,這裡我們使用匿名的類別來實做 ClickHandler,另外加入 KeyPressHandler,在按下 Enter 鍵時可以送出輸入的內容。package com.google.gwt.sample.stockwatcher.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;
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 addStockButton = new Button("Add");
private Label lastUpdatedLabel = new Label();
/**
* Entry point method.
*/
public void onModuleLoad() {
// Create table for stock data.
stocksFlexTable.setText(0, 0, "Symbol");
stocksFlexTable.setText(0, 1, "Price");
stocksFlexTable.setText(0, 2, "Change");
stocksFlexTable.setText(0, 3, "Remove");
// Assemble Add Stock panel.
addPanel.add(newSymbolTextBox);
addPanel.add(addStockButton);
// Assemble Main panel.
mainPanel.add(stocksFlexTable);
mainPanel.add(addPanel);
mainPanel.add(lastUpdatedLabel);
// Associate the Main panel with the HTML host page.
RootPanel.get("stockList").add(mainPanel);
// Move cursor focus to the input box.
newSymbolTextBox.setFocus(true);
// Listen for mouse events on the Add button.
addStockButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
addStock();
}
});
// Listen for keyboard events in the input box.
newSymbolTextBox.addKeyPressHandler(new KeyPressHandler() {
public void onKeyPress(KeyPressEvent event) {
if (event.getCharCode() == KeyCodes.KEY_ENTER) {
addStock();
}
}
});
}
/**
* Add stock to FlexTable. Executed when the user clicks the addStockButton
* or presses enter in the newSymbolTextBox.
*/
private void addStock() {
final String symbol = newSymbolTextBox.getText().toUpperCase().trim();
newSymbolTextBox.setFocus(true);
// Stock code must be between 1 and 10 chars that are numbers, letters,
// or dots.
if (!symbol.matches("^[0-9A-Z\\.]{1,10}$")) {
Window.alert("'" + symbol + "' is not a valid symbol.");
newSymbolTextBox.selectAll();
return;
}
newSymbolTextBox.setText("");
// TODO Don't add the stock if it's already in the table.
// TODO Add the stock to the table.
// TODO Add a button to remove this stock from the table.
// TODO Get the stock price.
}
}
從 49 行到 56 行是將 addStockButton 加入一個 ClickHandler,當 Add 按鈕被按下時,就會呼叫 addStock() 函數,而從 58 行到 65 行也是類似的做作用,當使用者按下 Enter 鍵時,則會呼叫 addStock() 函數。
從 69 行到 92 行是新定義的 addStock() 函數,在使用者輸入資料後,會檢查資料是否正確。
從第 4 行到第 9 行是新增的 import,通常使用 Eclipse 會提示你該新增哪一些。
這裡我們使用匿名的類別來新增 Event Handler,這是因為這個 Event Handler 很簡單,若是較複雜的 Event Handler 則使用一般的方式定義類別會比較好。
測試 Event Handler
將程式存檔後,就可以測試 Event Handler 了,若是輸入不用確的字串,則會出現錯誤的訊息:客戶端程式碼
接下來要加入在客戶端的程式碼,以便處理一些客戶端的動作:- 新增或移除 stock 資料。
- 定期更新 stock 資料。
- 顯示上次更新的時間。
新增資料結構
首先新增加一個資料結構,用來儲存使用者所輸入資料,我們直接使用 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 addStockButton = new Button("Add");
private Label lastUpdatedLabel = new Label();
private ArrayList<String> stocks = new ArrayList<String>();
依照 Eclipse 的提示加入必要的 import
import java.util.ArrayList;
在 Flex Table 中加入資料
修改 addStock() 函數。檢查使用者所輸入的資料是否重複:// TODO Don't add the stock if it's already in the table.
if (stocks.contains(symbol))
return;
若資料沒有重複,則新增之:
// TODO Add the stock to the table.
int row = stocksFlexTable.getRowCount();
stocks.add(symbol);
stocksFlexTable.setText(row, 0, symbol);
加入刪除 stock 的按鈕:
// TODO Add a button to remove this stock from the table.
Button removeStockButton = new Button("x");
removeStockButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
int removedIndex = stocks.indexOf(symbol);
stocks.remove(removedIndex);
stocksFlexTable.removeRow(removedIndex + 1);
}
});
stocksFlexTable.setWidget(row, 3, removeStockButton);
測試新增/移除 Stock
存檔後,測試新增與移除 stock 的功能:定時更新資料
在傳統的網頁中若需要定時更新網頁中的資料,最常見的方式就是定時重新載入網頁,但這種方式會占用掉大量的資源,在 Web 2.0 的技術中,有更好的方式可以達到這樣的效果。GWT 中提供了 Timer 類別可以處理這種定時更新的需求,Timer 是一個單執行緒、跨瀏覽器的類別,它可以讓你在設定的時間點執行某一段程式。
// Move cursor focus to the text box.
newSymbolTextBox.setFocus(true);
// Setup timer to refresh list automatically.
Timer refreshTimer = new Timer() {
@Override
public void run() {
refreshWatchList();
}
};
refreshTimer.scheduleRepeating(REFRESH_INTERVAL);
依照 Eclipse 的提示加入 import
import com.google.gwt.user.client.Timer;
定義 REFRESH_INTERVAL,設定多久更新一次
public class StockWatcher implements EntryPoint {
private static final int REFRESH_INTERVAL = 5000; // ms
private VerticalPanel mainPanel = new VerticalPanel();
在 addStock() 函數的結尾加上下面這行
// TODO Get the stock price.
refreshWatchList();
最後在 StockWatcher 類別中加入一個方法:
private void refreshWatchList() {
// TODO Auto-generated method stub
}
當 Timer 啟動時,它會去執行 run() 函數,這裡我們直接讓他呼叫 refreshWatchList() 函數,接下來我們要實做 refreshWatchList() 函數。
包裝 Stock 資料
使用 GWT 可以加速往頁開發的原因在於其可以使用 Java 的方式開發,這裡我們使用一個類別來實做 stock 的資料,首先新增一個 Java 的類別,首先在 Eclipse 選擇 com.google.gwt.sample.stockwatcher.client,然後在選單列中選擇 File > New > Class:填入 Class 的名稱:StockPrice,剩下的使用預設的選項,按下 Finish。建立好了 StockPrice 類別之後,要撰寫其內部的程式碼,這是一個基本的類別,實作方式很簡單:
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;
}
}
接下來我們使用隨機的亂數指定 stock 的資料,以實做 refreshWatchList():
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(stocks.get(i), price, change);
}
updateTable(prices);
}
再加上必要的 import
import com.google.gwt.user.client.Random;
在 StockWatcher 類別中加入一個 updateTable 方法,這個將用來更新 Flex Table 的內容:
private void updateTable(StockPrice[] prices) {
for (int i = 0; i < prices.length; i++) {
updateTable(prices[i]);
}
// Display timestamp showing last refresh.
lastUpdatedLabel.setText("Last update : "
+ DateTimeFormat.getMediumDateTimeFormat().format(new Date()));
}
private void updateTable(StockPrice price) {
// Make sure the stock is still in the stock table.
if (!stocks.contains(price.getSymbol())) {
return;
}
int row = stocks.indexOf(price.getSymbol()) + 1;
// Format the data in the Price and Change fields.
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());
// Populate the Price and Change fields with new data.
stocksFlexTable.setText(row, 1, priceText);
stocksFlexTable.setText(row, 2, changeText + " (" + changePercentText
+ "%)");
}
加入必要的 import
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.i18n.client.DateTimeFormat;
import java.util.Date;
最後存檔測試:
這樣基本的程式部分就大功告成了!
hahahahahha nice 1
回覆刪除Let me try if its working
回覆刪除