GWT-Ext 是基于 Google Web Toolkit(GWT)和 ExtJs 的功能强大的网页开发控件库。它非常适用于进行纯 Java 语言的富 Internet 应用的快速开发。本系列文章将详细讲解 GWT-Ext 的基本结构和功能特点,并通过代码示例来演示该技术的具体实现。本文是该系列的最后一部分,将体验拖拽的效果,了解常用的两种拖拽方式和一些经验总结。在对通信的介绍中,本文还将对同步通信和异步通信进行详细介绍。
拖拽
在 GWT-EXT 中实现拖拽功能比较简单。GWT-EXT 在 com.gwtext.client.dd 包中提供了与拖拽相关的类。图 1 展示了这些类的关系。
图 1. com.gwtext.client.dd 包中与拖拽相关的类的关系图
其中,DragDrop 是一个基类,它定义了一些可以被拖拽的元素的接口和基本操作,如 startDrag, onDrag, onDragOver 和 onDragOut 等 Drag 事件。而继承自这个类的子类,功能上主要分为两类。一个是可以使得对象被拖动;一个是使得拖动对象可以被放置在 DropTarget 中。
首先,介绍一些能够帮助对象被拖动的类。
DD 类
用户可以通过调用 DD 的构造函数来使得对象能够被拖动。这种拖动使得对象会跟随鼠标的移动而移动。
DD dd = new DD(Component component);// 参数 component 是被拖动的对象 |
DDProxy 类
DDProxy 类继承自 DD 类。使用这个类来构造被拖动的对象时,该对象的边框会跟随鼠标的移动而移动。而等到鼠标释放时,该对象会被重新放置到鼠标停止的位置。
DD dd = new DDProxy(Component component);// 参数 component 是被拖动的对象 |
这里,举一个拖动 Panel 的例子。首先,定义一个 Panel,
Panel draggable = new Panel(); draggable.setTitle("Draggable"); draggable.setBorder(true); |
然后,将这个 Panel 作为参数来构造一个 DD 类 ,
DD dd = new DD(draggable); |
这样,这个 Panel 就可以被拖动了。
图 2. 对象随鼠标移动的 Panel
若将 draggable 这个 Panel 作为参数来构造 DDProxy 类,
DD dd = new DDProxy(draggable);则会出现这样的效果,
图 3. 边框随鼠标移动的 Panel
被移动的是 draggable Panel 的边框。
接下来,介绍一些被拖动对象可以被放置在其他对象中的功能类。这些类主要是 DDTarget 和 DragTarget,其中 DragTarget 继承自 DDTarget 。
DDTarget 类
将元素作为参数传递到 DDTarget 中,那么这个元素就可以是一个 Drop Target 。具体在应用中,我们一般使用 DragTarget 来完成这样的操作。
首先,用户需要将元素作为一个参数传递到 DragTarget 类的构造函数中。除此之外,还要定义一个 DropTargetConfig 类来配置 Drag Drop Group 的名字。这里,需要注意的有两点:
第一, 只有 Drag 元素和 DropTarget 元素具有同样 DragDropGroup 名字的,Drag 元素才能够被拖放到正确的 DropTarget 元素中去。方法如下 :
1. 构造 DropTargetConfig 类
DropTargetConfig cfg = new DropTargetConfig(); |
2. 指定 Drag Drop Group 名字
cfg.setdDdGroup(java.lang.String ddGroup);// 参数 ddGroup 指 drag drop group 的名字。 |
3. 调用 DropTarget 的构造函数来将拖拽元素和 DropTargetConfig 作为参数传入进去。
DropTarget tg = new DropTarget(Comopnent component ,DropTargetConfig cfg) |
第二, 在 DragTarget 中,还需要实现 notifyDrop(DragSource source, EventObject e, DragData data) 方法以实现拖动后的效果。其中,source 是指可以被拖动到 DropTarget 上的元素; e 是指当前的事件; data 是指被拖动元素所包含的数据对象。
这里,我们举一个从 Tree 中拖动 TreeNode 元素到 Grid 中的例子来说明上述步骤。
图 4. 从 Tree 中拖动 TreeNode 元素到 Grid 中
首先,定义 TreePanel 和 GridPanel,并定义 Drag Drop Group 的名字。
final TreePanel treePanel = new TreePanel(); treePanel. setEnableDD(true); treePanel..setEnableDrop(true); final GridPanel gridPanel = new GridPanel(); gridPanel .setEnableDragDrop(true); tripTreePanel.setDdGroup("myDDGroup"); gridPanel.setDdGroup("myDDGroup"); |
然后,初始化一个 DropTargetConfig,并指定同样的 Drag Drop Group 的名字。
DropTargetConfig cfg = new DropTargetConfig(); cfg.setdDdGroup("myDDGroup"); // 指定了同样的 DDGroup |
最后,定义 DropTarget,以 gridPanel 和 cfg 为参数,并覆写 notifyDrop 函数。
DropTarget tg = new DropTarget(gridPanel,cfg) { public boolean notifyDrop(DragSource source, EventObject e, DragData data) { // …… } }; |
在 notifyDrop 函数中,可以实现从当前 Tree 中删除选中节点和在 Grid 中增加记录的操作。
通信
GWT-EXT 是 GWT 在界面功能上的扩展,但在通信方面,使用的仍然是 GWT 所提供的通信框架。作为 AJAX 的应用开发包,GWT 使得实现客户端和服务器的通信变得十分简单,特别是异步通信。在本文中,我们首先介绍 GWT 中用来开发异步通信应用的流程,然后介绍一个异步通信的例子。除此之外,对于同步通信,由于 GWT 没有提供特别的支持,但有时我们仍需以同步的方式与 Server 端交互,所以,我们提供了一种变通的方法,即通过 Form 提交 Action 的方式实现此效果,并通过一个文件下载的例子来讲述。
在 GWT 框架下实现异步通信
在 GWT 中,异步通信方面的开发变得非常简单。用户只需在服务器端定义一个 Service 接口及其实现,在客户端声明这样的接口,之后的事情,例如管道管理和数据的传输、转换等复杂的事情将由 GWT 负责。具体的过程,有以下几个步骤。
1. 在客户端定义服务接口。服务,就像是客户端与服务器所签署的一份合约,客户端首先要定义这样的服务规则,也就是一个接口。具体实现时,此接口要继承自 RemoteService 并保存在客户端。
Public interface MyService extends RemoteService{ Public List myRequestToServer(int requestParameters); } |
值得一提的是,GWT 中的 RPC 机制提供了通过 HTTP 协议在客户端和服务器端传送 java 对象的方法并加以封装。对于用户来说,只要使用 GWT 所能够支持的数据类型或对象作为参数和返回值就可以了。
2. 在客户端定义此服务的异步接口。为了应用 AJAX(被 GWT 所支持)所带来的异步特性,在客户端我们还需要定义一个此接口的异步接口。方法也很简单。
Public interface MyServiceAsync extends RemoteService{ Public void myRequestToServer(int requestParameters, AsyncCallback callback); } |