您的位置:首页 > 编程语言 > Go语言

试用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调整,不过我早告诉你,我对那些玩意不感兴趣。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: