UiCustomWidgets

GWT 使得创建自定义用户界面元素变得容易。有三种通用的策略可供遵循

有许多第三方库提供了您可以集成到 GWT 模块中的部件,这些部件是使用上面列出的策略创建的。

构建组合部件

创建新部件最有效的方法是扩展 Composite 类。组合部件是一种特殊的部件,它可以包含另一个组件(通常是 Panel),但表现得好像它就是其包含的部件。您可以轻松地将现有部件组组合成一个组合部件,它本身就是一个可重用的部件。GWT 中提供的一些 UI 组件就是组合部件:例如,TabPanel(一个由 TabBar 和 DeckPanel 组成的组合部件)和 SuggestBox

与其通过子类化 Panel 或其他 Widget 类型来创建复杂的部件,不如创建一个组合部件,因为组合部件通常希望控制哪些方法是公开可访问的,而不公开从其 Panel 超类继承的那些方法。

示例组合部件

以下代码片段展示了如何创建一个由 TextBox 部件和 CheckBox 部件组成的组合部件,它们在 VerticalPanel 中进行布局。

package com.google.gwt.examples;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.CheckBox;
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;

public class CompositeExample implements EntryPoint {

  /**
   * A composite of a TextBox and a CheckBox that optionally enables it.
   */
  private static class OptionalTextBox extends Composite implements
      ClickHandler {

    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.addClickHandler(this);

      // All composites must call initWidget() in their constructors.
      initWidget(panel);

      // Give the overall composite a style name.
      setStyleName("example-OptionalCheckBox");
    }

    public void onClick(ClickEvent event) {
      Object sender = event.getSource();
      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);
  }
}

从头开始用 Java 代码创建

也可以从头开始创建一个部件,虽然比较棘手,因为您需要在更低的级别编写代码。许多基本部件都是以这种方式编写的,例如 ButtonTextBox。请参考这些部件的实现来了解如何创建自己的部件。

要了解如何创建自己的部件,请参考这些部件在 com.google.gwt.user.client.ui 包中的实现。源代码位于 gwt-user.jar 中。

使用 JavaScript

当实现直接从 Widget 基类派生的自定义部件时,您也可以使用 JavaScript 编写一些部件的方法。通常,这应该作为最后的手段,因为您需要考虑您编写的本机方法的跨浏览器影响,而且调试也变得更加困难。有关在实践中使用此模式的示例,请参见 TextBox 部件以及 TextBoxImpl 类中对其某些方法的底层 JavaScript 实现。您应该使用 延迟绑定 来隔离特定于浏览器的代码。