试用Google Web Toolkit(2)
2006-05-20 14:18
633 查看
把GWT中sample目录中的KitchenSink按(1)中的步骤建立一个eclipse工程
projectCreator -eclipse KitchenSink
applicationCreator -eclipse KitchenSink com.google.gwt.sample.kitchensink.client. KitchenSink
在把sample/KitchenSink/com/.../kitchensink目录下的client和public拷贝过来,这个工程实际上演示GWT中的主要UI组件。
在GWT中如果想要创造一个复杂组件,你需要从Composite类派生一个子类,在这个子类中,你可以封装一系列其他从Widget派生的组件,对外提供一致的抽象接口。
比如,我想写一个类似于一般IDE中都提供的属性编辑器,很显然,这个东西由多个属性编辑项(Item)构成,而每个属性项目包括属性的名字以及他对应的值,这个值可以由Text, Combox, List, Dialog等等你能想到的一切能输入值的组件构成。
首先来看看我们的基本单位PropertyItem(属性项)应该是个什么样子。
package com.google.gwt.sample.kitchensink.client.custom;
// 从Composite 继承,组合两个组件属性名字和属性值
public class PropertyItem extends Composite {
// 用id来唯一标识每个item
private String id;
// 属性的名字,选择用Label或是HTML控件
private HTML nameView;
// 属性值的编辑器
private BaseEditor valueView;
// panel,放置属性名字和属性值的容器组件,这是一个横向排列的panel
private HorizontalPanel container = new HorizontalPanel();
}
最大的麻烦恐怕就是属性值的编辑器了,因为它可以是一个任何可能的编辑器,考虑把它抽象为一个接口;
package com.google.gwt.sample.kitchensink.client.custom;
import com.google.gwt.user.client.ui.Widget;
public interface Editable {
// 一个属性值编辑器必须能取值和设置值,当然这个值对象可能更复杂一些,不过先用一个String类就够了
public String getValue();
public void setValue(String value);
// 这个编辑器需要暴露它的最高层的UI组件,以便显示在PropertyItem中。
public Widget getWidget();
}
接下来要考虑的事情是:在属性值的编辑器的值发生变化时,外部可以接收到值变化的事件。
package com.google.gwt.sample.kitchensink.client.custom;
public interface ChangeListener {
public void onChange(Editable sender);
}
每个属性值编辑器都是一个事件源,需要提供注册事件捕捉器的能力。
package com.google.gwt.sample.kitchensink.client.custom;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public abstract class BaseEditor implements Editable {
private List listeners = new ArrayList();
public BaseEditor() {
}
public boolean addChangeListener(ChangeListener listener) {
return listeners.add(listener);
}
public boolean removeChangeListener(ChangeListener listener) {
return listeners.remove(listener);
}
public ChangeListener removeChangeListener(int index) {
return (ChangeListener)listeners.remove(index);
}
public void notifyAllChangeListeners() {
for (Iterator iter= listeners.iterator(); iter.hasNext();) {
((ChangeListener)iter.next()).onChange(this);
}
}
}
看看如何实现一个基本的属性编辑器,比如一个最普通的文本输入框,它只是对TextBox组件一个adaptor。
package com.google.gwt.sample.kitchensink.client.custom;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
public class TextEditor extends BaseEditor implements com.google.gwt.user.client.ui.ChangeListener {
private TextBox editor = new TextBox();
public TextEditor() {
super();
editor.addChangeListener(this);
}
public String getValue() {
return editor.getText();
}
public void setValue(String value) {
editor.setText(value);
}
public void onChange(Widget sender) {
if (sender == editor) {
notifyAllChangeListeners();
}
}
public Widget getWidget() {
return editor;
}
}
然后把它填充到PropertyItem中去:
package com.google.gwt.sample.kitchensink.client.custom;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Widget;
public class PropertyItem extends Composite {
private String id;
private HTML nameView;
private BaseEditor valueView;
private HorizontalPanel container = new HorizontalPanel();
/* VerticalPanel left = new VerticalPanel();
VerticalPanel right = new VerticalPanel();*/
public PropertyItem(String id) {
this(id, "label", EditorType.Text, "");
}
public PropertyItem(String id, String name, int editorType, String value) {
this.id = id;
setNameView(new HTML(name));
setValueView(EditorFactory.create(editorType));
setValue(value);
adjustPosition();
setWidget(container);
}
public void setNameView(HTML view) {
refresh(nameView, view, 0);
nameView = view;
}
public void setValueView(BaseEditor view) {
Widget widget = null;
if (null != valueView) widget = valueView.getWidget();
refresh(widget, view.getWidget(), 1);
valueView = view;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
nameView.setHTML(name);
}
public void setValue(String value) {
valueView.setValue(value);
}
public String getValue() {
return valueView.getValue();
}
public String getName() {
return nameView.getHTML();
}
public void addChangeListener(ChangeListener listener) {
valueView.addChangeListener(listener);
}
public HTML getNameView() {
return nameView;
}
public BaseEditor getValueView() {
return valueView;
}
public void refresh(Widget oldView, Widget newView, int index) {
int oldIndex = -1;
if (oldView != null) oldIndex = container.getWidgetIndex(oldView);
if (oldIndex != -1) container.remove(oldView);
int setIndex = (oldIndex == -1) ? index : oldIndex;
container.insert(newView, setIndex);
}
public void adjustPosition() {
nameView.setStyleName("inspector-item-name");
container.setCellWidth(nameView, "50%");
container.setCellWidth(valueView.getWidget(), "50%");
container.setCellVerticalAlignment(nameView, HasVerticalAlignment.ALIGN_MIDDLE);
container.setCellVerticalAlignment(valueView.getWidget(), HasVerticalAlignment.ALIGN_MIDDLE);
container.setCellHorizontalAlignment(nameView, HasHorizontalAlignment.ALIGN_LEFT);
container.setCellHorizontalAlignment(valueView.getWidget(), HasHorizontalAlignment.ALIGN_LEFT);
}
}
有了PropertyItem,把他们组合在一个垂直排列的panel内,就可以组成一个简单的PropertyEditor.
package com.google.gwt.sample.kitchensink.client.custom;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.VerticalPanel;
public class Inspector extends Composite {
VerticalPanel container = new VerticalPanel();
private List itemList = new ArrayList();
public Inspector() {
super();
container.setStyleName("inspector");
setWidget(container);
}
public void addItemView(PropertyItem item) {
container.add(item);
}
public void removeItemView(PropertyItem item) {
container.remove(item);
}
public void addItem(PropertyItem item) {
itemList.add(item);
addItemView(item);
}
public void removeItem(PropertyItem item) {
itemList.remove(item);
removeItemView(item);
}
public void addItem(String id, String name, int editorType, String value) {
addItem(new PropertyItem(id, name, editorType, value));
}
public PropertyItem getItem(String id) throws ItemNotFoundException {
for (Iterator iter = itemList.iterator(); iter.hasNext();) {
PropertyItem item = (PropertyItem)iter.next();
if (item.getId().equalsIgnoreCase(id)) {
return item;
}
}
throw new ItemNotFoundException("item " + id + "not found");
}
public void removeItem(String id) throws ItemNotFoundException {
PropertyItem item = getItem(id);
removeItem(item);
}
private void addChangeListenerInternal(String id, ChangeListener listener) throws ItemNotFoundException {
getItem(id).addChangeListener(listener);
}
public boolean addChangeListener(String id, ChangeListener listener) {
try {
addChangeListenerInternal("t1", listener);
return true;
} catch (ItemNotFoundException e) {
return false;
}
}
}
要在kitchensink项目中测试这个组件,可以仿造其中的Buttons类:
package com.google.gwt.sample.kitchensink.client;
import com.google.gwt.sample.kitchensink.client.custom.Editable;
import com.google.gwt.sample.kitchensink.client.custom.EditorType;
import com.google.gwt.sample.kitchensink.client.custom.Inspector;
import com.google.gwt.user.client.ui.*;
public class PropertyEditor extends Sink implements com.google.gwt.sample.kitchensink.client.custom.ChangeListener {
public static SinkInfo init() {
return new SinkInfo("PropertyEditor",
"Composite class build <code>PropertyEditor</code>") {
public Sink createInstance() {
return new PropertyEditor();
}
};
}
private void setInspector() {
Inspector inspector = new Inspector();
inspector.addItem("t1", "key", EditorType.Text, "dddd");
inspector.addItem("t2", "cdasfas", EditorType.Text, "asdfsaf");
// All composites must call setWidget() in their constructors.
setWidget(inspector);
}
/**
* Constructs an OptionalTextBox with the given caption on the check.
*
* @param caption the caption to be displayed with the check box
*/
public PropertyEditor() {
// Place the check above the text box using a vertical panel.
setInspector();
// Give the overall composite a style name.
setStyleName("example-OptionalCheckBox");
}
public void onChange(Editable sender) {
System.out.println(sender.getValue());
}
}
当然,这很丑陋,可以利用css调整,不过我早告诉你,我对那些玩意不感兴趣。
projectCreator -eclipse KitchenSink
applicationCreator -eclipse KitchenSink com.google.gwt.sample.kitchensink.client. KitchenSink
在把sample/KitchenSink/com/.../kitchensink目录下的client和public拷贝过来,这个工程实际上演示GWT中的主要UI组件。
在GWT中如果想要创造一个复杂组件,你需要从Composite类派生一个子类,在这个子类中,你可以封装一系列其他从Widget派生的组件,对外提供一致的抽象接口。
比如,我想写一个类似于一般IDE中都提供的属性编辑器,很显然,这个东西由多个属性编辑项(Item)构成,而每个属性项目包括属性的名字以及他对应的值,这个值可以由Text, Combox, List, Dialog等等你能想到的一切能输入值的组件构成。
首先来看看我们的基本单位PropertyItem(属性项)应该是个什么样子。
package com.google.gwt.sample.kitchensink.client.custom;
// 从Composite 继承,组合两个组件属性名字和属性值
public class PropertyItem extends Composite {
// 用id来唯一标识每个item
private String id;
// 属性的名字,选择用Label或是HTML控件
private HTML nameView;
// 属性值的编辑器
private BaseEditor valueView;
// panel,放置属性名字和属性值的容器组件,这是一个横向排列的panel
private HorizontalPanel container = new HorizontalPanel();
}
最大的麻烦恐怕就是属性值的编辑器了,因为它可以是一个任何可能的编辑器,考虑把它抽象为一个接口;
package com.google.gwt.sample.kitchensink.client.custom;
import com.google.gwt.user.client.ui.Widget;
public interface Editable {
// 一个属性值编辑器必须能取值和设置值,当然这个值对象可能更复杂一些,不过先用一个String类就够了
public String getValue();
public void setValue(String value);
// 这个编辑器需要暴露它的最高层的UI组件,以便显示在PropertyItem中。
public Widget getWidget();
}
接下来要考虑的事情是:在属性值的编辑器的值发生变化时,外部可以接收到值变化的事件。
package com.google.gwt.sample.kitchensink.client.custom;
public interface ChangeListener {
public void onChange(Editable sender);
}
每个属性值编辑器都是一个事件源,需要提供注册事件捕捉器的能力。
package com.google.gwt.sample.kitchensink.client.custom;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public abstract class BaseEditor implements Editable {
private List listeners = new ArrayList();
public BaseEditor() {
}
public boolean addChangeListener(ChangeListener listener) {
return listeners.add(listener);
}
public boolean removeChangeListener(ChangeListener listener) {
return listeners.remove(listener);
}
public ChangeListener removeChangeListener(int index) {
return (ChangeListener)listeners.remove(index);
}
public void notifyAllChangeListeners() {
for (Iterator iter= listeners.iterator(); iter.hasNext();) {
((ChangeListener)iter.next()).onChange(this);
}
}
}
看看如何实现一个基本的属性编辑器,比如一个最普通的文本输入框,它只是对TextBox组件一个adaptor。
package com.google.gwt.sample.kitchensink.client.custom;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;
public class TextEditor extends BaseEditor implements com.google.gwt.user.client.ui.ChangeListener {
private TextBox editor = new TextBox();
public TextEditor() {
super();
editor.addChangeListener(this);
}
public String getValue() {
return editor.getText();
}
public void setValue(String value) {
editor.setText(value);
}
public void onChange(Widget sender) {
if (sender == editor) {
notifyAllChangeListeners();
}
}
public Widget getWidget() {
return editor;
}
}
然后把它填充到PropertyItem中去:
package com.google.gwt.sample.kitchensink.client.custom;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Widget;
public class PropertyItem extends Composite {
private String id;
private HTML nameView;
private BaseEditor valueView;
private HorizontalPanel container = new HorizontalPanel();
/* VerticalPanel left = new VerticalPanel();
VerticalPanel right = new VerticalPanel();*/
public PropertyItem(String id) {
this(id, "label", EditorType.Text, "");
}
public PropertyItem(String id, String name, int editorType, String value) {
this.id = id;
setNameView(new HTML(name));
setValueView(EditorFactory.create(editorType));
setValue(value);
adjustPosition();
setWidget(container);
}
public void setNameView(HTML view) {
refresh(nameView, view, 0);
nameView = view;
}
public void setValueView(BaseEditor view) {
Widget widget = null;
if (null != valueView) widget = valueView.getWidget();
refresh(widget, view.getWidget(), 1);
valueView = view;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public void setName(String name) {
nameView.setHTML(name);
}
public void setValue(String value) {
valueView.setValue(value);
}
public String getValue() {
return valueView.getValue();
}
public String getName() {
return nameView.getHTML();
}
public void addChangeListener(ChangeListener listener) {
valueView.addChangeListener(listener);
}
public HTML getNameView() {
return nameView;
}
public BaseEditor getValueView() {
return valueView;
}
public void refresh(Widget oldView, Widget newView, int index) {
int oldIndex = -1;
if (oldView != null) oldIndex = container.getWidgetIndex(oldView);
if (oldIndex != -1) container.remove(oldView);
int setIndex = (oldIndex == -1) ? index : oldIndex;
container.insert(newView, setIndex);
}
public void adjustPosition() {
nameView.setStyleName("inspector-item-name");
container.setCellWidth(nameView, "50%");
container.setCellWidth(valueView.getWidget(), "50%");
container.setCellVerticalAlignment(nameView, HasVerticalAlignment.ALIGN_MIDDLE);
container.setCellVerticalAlignment(valueView.getWidget(), HasVerticalAlignment.ALIGN_MIDDLE);
container.setCellHorizontalAlignment(nameView, HasHorizontalAlignment.ALIGN_LEFT);
container.setCellHorizontalAlignment(valueView.getWidget(), HasHorizontalAlignment.ALIGN_LEFT);
}
}
有了PropertyItem,把他们组合在一个垂直排列的panel内,就可以组成一个简单的PropertyEditor.
package com.google.gwt.sample.kitchensink.client.custom;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.HasVerticalAlignment;
import com.google.gwt.user.client.ui.VerticalPanel;
public class Inspector extends Composite {
VerticalPanel container = new VerticalPanel();
private List itemList = new ArrayList();
public Inspector() {
super();
container.setStyleName("inspector");
setWidget(container);
}
public void addItemView(PropertyItem item) {
container.add(item);
}
public void removeItemView(PropertyItem item) {
container.remove(item);
}
public void addItem(PropertyItem item) {
itemList.add(item);
addItemView(item);
}
public void removeItem(PropertyItem item) {
itemList.remove(item);
removeItemView(item);
}
public void addItem(String id, String name, int editorType, String value) {
addItem(new PropertyItem(id, name, editorType, value));
}
public PropertyItem getItem(String id) throws ItemNotFoundException {
for (Iterator iter = itemList.iterator(); iter.hasNext();) {
PropertyItem item = (PropertyItem)iter.next();
if (item.getId().equalsIgnoreCase(id)) {
return item;
}
}
throw new ItemNotFoundException("item " + id + "not found");
}
public void removeItem(String id) throws ItemNotFoundException {
PropertyItem item = getItem(id);
removeItem(item);
}
private void addChangeListenerInternal(String id, ChangeListener listener) throws ItemNotFoundException {
getItem(id).addChangeListener(listener);
}
public boolean addChangeListener(String id, ChangeListener listener) {
try {
addChangeListenerInternal("t1", listener);
return true;
} catch (ItemNotFoundException e) {
return false;
}
}
}
要在kitchensink项目中测试这个组件,可以仿造其中的Buttons类:
package com.google.gwt.sample.kitchensink.client;
import com.google.gwt.sample.kitchensink.client.custom.Editable;
import com.google.gwt.sample.kitchensink.client.custom.EditorType;
import com.google.gwt.sample.kitchensink.client.custom.Inspector;
import com.google.gwt.user.client.ui.*;
public class PropertyEditor extends Sink implements com.google.gwt.sample.kitchensink.client.custom.ChangeListener {
public static SinkInfo init() {
return new SinkInfo("PropertyEditor",
"Composite class build <code>PropertyEditor</code>") {
public Sink createInstance() {
return new PropertyEditor();
}
};
}
private void setInspector() {
Inspector inspector = new Inspector();
inspector.addItem("t1", "key", EditorType.Text, "dddd");
inspector.addItem("t2", "cdasfas", EditorType.Text, "asdfsaf");
// All composites must call setWidget() in their constructors.
setWidget(inspector);
}
/**
* Constructs an OptionalTextBox with the given caption on the check.
*
* @param caption the caption to be displayed with the check box
*/
public PropertyEditor() {
// Place the check above the text box using a vertical panel.
setInspector();
// Give the overall composite a style name.
setStyleName("example-OptionalCheckBox");
}
public void onChange(Editable sender) {
System.out.println(sender.getValue());
}
}
当然,这很丑陋,可以利用css调整,不过我早告诉你,我对那些玩意不感兴趣。
相关文章推荐
- 试用Google Web Toolkit (1)
- 使用 Google Web Toolkit、Apache Derby 和 Eclipse 构建 Ajax 应用程序 第 1 部分: 梦幻前端
- 试用Google的picasa web
- Google Web Toolkit Solutions: More Cool & Useful Stuff (Paperback), Nov.2007.eBook-BBL
- Google Web Toolkit (GWT)怎么制作多个用户界面
- 试用Google的picasa web
- 试用Google的picasa web
- Google Web Toolkit: GWT Java Ajax Programming
- Google Web Toolkit 入门
- 使用 Google Web Toolkit 开发 Ajax
- 面向 Java 开发人员的 Ajax: 使用 Google Web Toolkit 开发 Ajax
- Google Web Toolkit简介
- GWT笔记(Google Web Toolkit)1
- 使用 Google Web Toolkit、Apache Derby 和 Eclipse 构建 Ajax 应用程序,第 2 部分: 可靠后端
- 试用Google的picasa web
- GWT(google web toolkit)教程(一) 配置
- Accelerated GWT: Building Enterprise Google Web Toolkit Applications
- Google Web Toolkit 入门
- 面向 Java 开发人员的 Ajax: Google Web Toolkit 入门(GWT)
- GWT(Google Web Toolkit)学习