管理事件

此时,您已创建了界面的所有元素。与许多用户界面框架一样,GWT 是基于事件的。这意味着代码在响应某些事件发生时执行。大多数情况下,该事件是由用户触发的,用户使用鼠标或键盘与应用程序界面交互。

在本节中,您将连接小部件以侦听和处理鼠标和键盘事件。

  1. 回顾功能需求。
  2. 侦听事件。
  3. 响应事件。
  4. 测试事件处理。

回顾事件处理需求

让我们回顾一下 StockWatcher 需求,看看发生了哪些事件。

任务 UI 事件(触发机制) 响应
用户输入股票代码。 单击“添加”按钮或在输入框中按回车键。 创建删除按钮。
用户从表格中删除股票。 按下“删除”按钮。 从表格中删除行。

GWT 提供了许多不同的事件处理程序接口。要处理“添加”和“删除”按钮上的单击事件,您将使用 ClickHandler 接口。要处理输入框中的键盘事件,您将使用 KeyPressHandler 接口。

从 GWT 1.6 开始,ClickHandler、KeyDownHandler、KeyPressHandler 和 KeyUpHandler 接口已取代现在已弃用的 ClickListener 和 KeyBoardListener 接口。

侦听事件

事件处理程序接口

GWT 中的事件使用类似于其他用户界面框架的事件处理程序接口模型。要订阅事件,您将特定的事件处理程序接口传递给相应的小部件。事件处理程序接口定义了一个或多个方法,小部件随后调用这些方法来宣布(发布)事件。

处理鼠标事件

StockWatcher 用户输入股票代码的一种方法是使用鼠标单击“添加”按钮。

您将通过传递一个实现 ClickHandler 接口的对象来处理“添加”按钮的单击事件。在这种情况下,您将使用匿名内部类来实现 ClickHandler。ClickHandler 接口有一个方法 onClick,当用户单击小部件时会触发该方法。

当用户单击“添加”按钮时,StockWatcher 应该通过将股票添加到股票表格中来做出响应。因此,要处理单击事件,请调用 addStock 方法。您尚未编写 addStock 方法;您将在下一节中创建一个存根,然后对其进行编码。

  1. 向“添加”按钮添加事件处理程序,以便它可以接收单击事件。
    • 在 Stockwatcher.java 中,在 onModuleLoad 方法中,剪切并粘贴以下突出显示的代码,该代码被注释为“侦听“添加”按钮上的鼠标事件”。
    • Eclipse 标记 ClickHandler 并建议您包含导入声明。
  2. 包含 ClickHandler 和 ClickEvent 的导入声明。
    • Eclipse 标记 addStock。
  3. 在 StockWatcher.java 中,为 addStock 方法创建存根。
    • 选择 Eclipse 快捷键,在类型 'StockWatcher' 中创建方法 addStock()。或者从以下突出显示的代码中复制并粘贴。
    • 注意:根据您的 Eclipse 配置,它可能会使用受保护的访问修饰符创建 addStock 方法。您不会对 StockWatcher 进行子类化,因此稍后在实现 addStock 方法时,您会将其访问权限更改为私有。
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.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();
      }
    });
  }

  /**
   * Add stock to FlexTable. Executed when the user clicks the addStockButton or
   * presses enter in the newSymbolTextBox.
   */
  private void addStock() {
    // TODO Auto-generated method stub
  }

}

实现说明:对于较小的应用程序(例如 StockWatcher)处理的事件相对较少,使用匿名内部类可以通过最少的代码完成工作。但是,如果您有大量事件处理程序订阅事件,这种方法效率低下,因为它会导致创建许多单独的事件处理程序对象。在这种情况下,最好让一个类实现事件处理程序接口,并处理来自多个事件发布者的事件。您可以通过调用其 getSource() 方法来区分事件的来源。这可以更好地利用内存,但需要更多代码。有关代码示例,请参见开发人员指南,事件处理程序.

处理键盘事件

除了使用“添加”按钮之外,StockWatcher 用户还可以通过在输入框中按回车键来输入股票代码,而无需将手从键盘上移开。

要订阅键盘事件,您可以调用 addKeyPressHandler(KeyPressHandler) 方法并将 KeyPressHandler 传递给它。

但是,对于回车键,您必须使用 KeyDownHandler 或 KeyUpHandler,因为 Firefox 不会正确填充 KeyPressEvent;请参阅 问题 5003.

  1. 连接输入框 newSymbolTextBox 的键盘按下事件处理程序。

    • 在 onModuleLoad 方法中,剪切并粘贴以下突出显示的代码,该代码被注释为“侦听输入框中的键盘事件”。
          // 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.addKeyDownHandler(new KeyDownHandler() {
            public void onKeyDown(KeyDownEvent event) {
              if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
                addStock();
              }
            }
          });
        }
    
        /**
         * Add stock to FlexTable. Executed when the user clicks the addStockButton or
         * presses enter in the newSymbolTextBox.
         */
        private void addStock() {
          // TODO Auto-generated method stub
        }
    
    • Eclipse 标记 KeyDownHandler 并建议您包含导入声明。
  2. 包含导入声明。

import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;

现在事件处理程序已连接,并已准备好接收事件。您的下一步是填写 addStock 存根方法。

响应用户事件

此时,StockWatcher 应该在侦听用户输入,即鼠标或键盘事件,它表示用户已输入股票代码。因此,接下来您将通过编码 StockWatcher 在检测到事件时应该做出的响应来测试事件处理程序接口是否有效:添加股票。StockWatcher 在客户端做出响应,而无需将任何请求发送回服务器或重新加载 HTML 页面。

将股票添加到股票表格中

在 StockWatcher 中,用户将一次在一个输入框中输入他们想要监控的股票的股票代码。当他们按下回车键或单击“添加”按钮时,您希望 StockWatcher 按如下方式做出响应

  1. 验证输入。
  2. 检查重复项。
  3. 添加股票。
  4. 添加一个用于从列表中删除股票的按钮。

在本节中,您将对第一个响应进行编码,即验证输入,只是为了查看事件处理程序接口是否有效。在下一节中,在客户端编码功能,您将对添加股票的剩余步骤进行编码。

您将在 addStock 方法中实现此功能。

验证文本框中的输入

您想验证输入的股票代码是否有效。在本次教程中,您将只执行一个简单的字符有效性检查,而不是验证用户输入是否与实际股票代码匹配。

首先,提取股票代码。要检索 TextBox 小部件中的文本,请使用其 getText 方法。

接下来,确保字符不在您指定的非法字符集中。在将用户输入转换为标准形式后,请使用正则表达式检查其格式。请记住使用在 Java 和 JavaScript 中具有相同含义的正则表达式。

如果输入有效,请清除文本框,以便用户可以添加另一个股票代码。

最后,如果输入无效,请通过对话框警告用户。

  1. 验证用户输入的股票代码。

    • 在 StockWatcher.java 中。用以下代码替换存根 addStock 方法。
        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.
        }
    
    • Eclipse 标记 Window 并建议您包含导入声明。
  2. 包含导入声明。

import com.google.gwt.user.client.Window;

测试事件处理

此时,您应该能够在输入框中输入文本。如果您使用非法字符,将弹出一个对话框并显示警告。试一试,看看。

  1. 在开发模式下测试事件处理。
    • 在已打开的浏览器中按刷新键。
  2. 测试两个事件处理程序接口是否都有效。
    • 在输入框中输入股票代码。可以使用两种方法输入:按下回车键或使用鼠标点击“添加”按钮。
    • 此时,股票还没有添加到表格中。但是,输入框应该清空,以便您可以添加另一个股票。
  3. 测试有效性检查和错误消息。
    • 输入一些包含非法字符的错误内容。

Validation Error Message

提示: 在按下刷新按钮后,您对 Java 代码所做的更改会立即显示在浏览器中。如果开发模式已在运行,则无需重新启动它。只需点击浏览器中的刷新按钮重新加载更新的 GWT 代码即可。

虽然您还没有编译 StockWatcher,但您可以在生产模式下在此处进行测试:运行 StockWatcher

下一步

到目前为止,您已经为鼠标和键盘事件实现了事件处理程序接口,这些事件表明用户已经输入了一个股票。StockWatcher 通过验证输入来响应。

现在,您已准备好实现客户端上的代码,将股票添加到表格中,并提供一个按钮来删除它。您还将显示股票价格以及显示数据和一个显示数据最后更新时间的时间戳。

步骤 5:在客户端编码功能