|
个人觉得,GWT的客户端表现并不是Gwt这个项目最关心的方向,所以要做出表现丰富的界面,要花去不少心思,当你为做一个“可排序的Grid”被搞得焦头烂额时,想想EXT,DOJO,只有艳羡地分了。
GWT-Ext 是sanjiv.jivan为了丰富GWT的客户端表现而贡献的开源项目。项目结合了当前客户端表现和用户体验都相当完善的Ext,提供了一种操作性很强的RIA开发方式。
作者应该花了不少心思在项目上,更新很频繁,大概不到1个月就有新的版本问世,目前项目的版本为GWT-Ext 0.9.3,是 Ext 1.1.1 和 GWT 1.4 Final 的结合,在 Ext 方面实现了大多数常用的控件,如Grid、Tree、Form、TabPanel等等。具体实现效果可以查看项目中的 Showcase Demo 。
以下结合一个例子来演示一下如何使用GWT-Ext 做实际开发。
一定要认真阅读项目中的 GettingStarted ,下面起初的几段其实就是该文的中文译本。
一、在Gwt项目中集成GWT-Ext
1.下载gwtext-0.9.3.zip,之后解压,将其中的 gwtext.jar 附加到当前GWT项目(Tree)的BuildPath中。
2.下载ext-1.1.1.zip (注意:暂时还不支持最新的2.0版本),将的ext-all.js、ext-core.js以及resources和adapter两个目录拷贝到module的public中的js/ext位置。对Ext熟悉的话,可以只拷贝需要的文件而不必载入所有的资源文件。
3.修改GWT项目中module的html页面,添加Ext资源,修改后的html页面可能是这样:
html代码
<html>
<head>
<title>Wrapper HTML for Treetitle>
<meta name='gwt:module' content='showcase.Tree'/>
<link type="text/css" rel='stylesheet' href='Tree.css'/>
<link rel="stylesheet" type="text/css" href="js/ext/resources/css/ext-all.css"/>
<link rel="stylesheet" type="text/css" href="js/ext/resources/css/xtheme-aero.css" />
<script type="text/javascript" src="js/ext/adapter/yui/yui-utilities.js">script>
<script type="text/javascript" src="js/ext/adapter/yui/ext-yui-adapter.js">script>
<script type="text/javascript" src="js/ext/ext-all.js">script>
head>
<body>
<script language="javascript" src="gwt.js">script>
<iframe id="__gwt_historyFrame" style="width:0;height:0;border:0">iframe>
body>
html>
4.编辑项目的Tree.gwt.xml文件,添加以下
xml 代码
<inherits name='com.gwtext.GwtExt'/>
通过以上步骤,你就可以写接近Ext功能的客户端界面了,同时也具有了Gwt的各种开发优势了,比如Java方式开发,清晰的RPC(这点尤其是在客户端需要获取服务器端数据信息时尤其方便)等等。
二、实例
下面我们就编写Showcase Demo 中的Tree节点下的Two Trees Drag & Drop,例子实现的是两个Tree中节点的任意拖放(再次感叹Ext的丰富表现)。
Tree.java代码如下,可直接拷贝到查看效果。
java 代码
package showcase.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.RootPanel;
import com.gwtext.client.widgets.tree.AsyncTreeNode;
import com.gwtext.client.widgets.tree.AsyncTreeNodeConfig;
import com.gwtext.client.widgets.tree.TreePanel;
import com.gwtext.client.widgets.tree.TreeNode;
import com.gwtext.client.widgets.tree.DropNodeCallback;
import com.gwtext.client.widgets.tree.TreePanelConfig;
import com.gwtext.client.widgets.tree.XMLTreeLoader;
import com.gwtext.client.widgets.tree.XMLTreeLoaderConfig;
import com.gwtext.client.widgets.tree.event.TreePanelListenerAdapter;
import com.gwtext.client.dd.*;
/**
* Entry point classes define onModuleLoad().
*/
public class Tree implements EntryPoint {
public void onModuleLoad() {
RootPanel rootPanel = RootPanel.get();
HorizontalPanel horizontalPanel = new HorizontalPanel();
rootPanel.add(horizontalPanel);
// create source countried tree
final TreePanel treePanel = new TreePanel("coutries-grouped", new TreePanelConfig() {
{
setAnimate(true);
setEnableDD(true);
setContainerScroll(true);
setRootVisible(true);
}
});
final XMLTreeLoader loader = new XMLTreeLoader(new XMLTreeLoaderConfig() {
{
setDataUrl("countries-grouped.xml");
setMethod("get");
setRootTag("countries");
setFolderTitleMapping("@title");
setFolderTag("continent");
setLeafTitleMapping("@title");
setLeafTag("country");
setQtipMapping("@qtip");
setIconMapping("@icon");
}
});
AsyncTreeNode root = new AsyncTreeNode("Countries", new AsyncTreeNodeConfig() {
{
setLoader(loader);
}
});
treePanel.setRootNode(root);
treePanel.render();
root.expand();
treePanel.expandAll();
// create target vacation tree
final TreePanel tripTreePanel = new TreePanel("vacation-tree", new TreePanelConfig() {
{
setAnimate(true);
setEnableDD(true);
setContainerScroll(true);
setRootVisible(true);
}
});
final XMLTreeLoader tripLoader = new XMLTreeLoader(new XMLTreeLoaderConfig() {
{
setDataUrl("trip.xml");
setMethod("get");
setRootTag("vacations");
setFolderIdMapping("@title");
setFolderTag("trip");
setQtipMapping("@qtip");
setIconMapping("@icon");
setAttributeMappings(new String[]{"@trip"});
}
});
AsyncTreeNode tripRoot = new AsyncTreeNode("Places to Visit", new AsyncTreeNodeConfig() {
{
setLoader(tripLoader);
}
});
tripTreePanel.setRootNode(tripRoot);
tripTreePanel.render();
tripRoot.expand();
tripTreePanel.expandAll();
// add trip tree listener that handles move / copy logic
tripTreePanel.addTreePanelListener(new TreePanelListenerAdapter() {
public boolean doBeforeNodeDrop(TreePanel treePanel, TreeNode target, String point, DragDrop source, TreeNode dropNode, DropNodeCallback dropDropNodeCallback) {
if("true".equals(target.getAttribute("trip"))) {
}
return true;
}
});
horizontalPanel.add(treePanel);
horizontalPanel.add(tripTreePanel);
}
}
注意:例子中需要的两个数据文件需放置于public目录,熟悉Ext的应该很清楚。
编译后执行的效果如下图:
以上示例只是将该种开发方式的流程顺了一下,窥一斑以示全貌,Ext各种丰富的表现都可以实现。闲下来,再写一下将数据提供(其实就是一些多维数据而已)方式改为RPC,这样开发流程就完整了。
可以下载示例程序运行一下,证明我没骗你[img] |
|