UiCustomWidgets
GWT 使得创建自定义用户界面元素变得容易。有三种通用的策略可供遵循
- 创建一个组合了现有部件的部件。
- 创建一个完全用 Java 语言编写的全新部件。
- 创建一个使用 JSNI 方法包装 JavaScript 的部件。
有许多第三方库提供了您可以集成到 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 代码创建
也可以从头开始创建一个部件,虽然比较棘手,因为您需要在更低的级别编写代码。许多基本部件都是以这种方式编写的,例如 Button 和 TextBox。请参考这些部件的实现来了解如何创建自己的部件。
要了解如何创建自己的部件,请参考这些部件在 com.google.gwt.user.client.ui 包中的实现。源代码位于 gwt-user.jar 中。
使用 JavaScript
当实现直接从 Widget 基类派生的自定义部件时,您也可以使用 JavaScript 编写一些部件的方法。通常,这应该作为最后的手段,因为您需要考虑您编写的本机方法的跨浏览器影响,而且调试也变得更加困难。有关在实践中使用此模式的示例,请参见 TextBox 部件以及 TextBoxImpl 类中对其某些方法的底层 JavaScript 实现。您应该使用 延迟绑定 来隔离特定于浏览器的代码。