第三章:表单和窗口
本章我们要学习GXT的表单功能。了解相关的表单components和如何使用他们。也会涉及到GXT Registry,来学习如何跨越各个components来传递对象的。
本章,我们会涉及到如下GXt功能集
- The full range of fields available in GXT
- FormPanel
- FormLayout
- Window
- FitLayout
- FieldMessages
- Form submission
- Working with GWT RPC
- Using the registry
RSSReader项目新增需求
目前为止, 我们的RSSReader虚拟项目已经有一个大致的雏形了。但对于经常发散思维的用户来说,如此的一个小RSSReader项目,功能上是无法满足用户需求的。比如用户就说了:现在不仅仅可以通过URL获得RSS信息,还可以自己创建他们。这就意味着我们需要创建一个表单,给用户提供录入的页面。对于GXT来说,这点需求不在话下。
RSS2.0规范
RSSReader项目可以按照RSS2.0的规范读取RSS的URL,来获得数据。一个简单的RSS feed其实就是个XML格式的标签包裹着指定的内容。因此如果想创建一个RSS feed就得按照其规范创建。
RSS2.0的详细说明:http://cyber.law.harvard.edu/rss/rss.html。例子:http://cyber.law.harvard.edu/rss/examples/rss2sample.xml
简单来说,一个RSS的xml有channel和多个RSS feed的item组成的。RSS feed的item大致是由:title,link,description三个元素组成,所以就要创建与之对应的两个表单(Form),一个用来接收channel信息,一个用来接收item信息。
FormPanel
FormPanel继承自ContentPanel,他可以管理有关表单的components。默认情况下,FormPanel的布局效果是设置成FormLayout。FormPanel只允许其添加Field的components,例如:TextField,LabelField等。如果添加了其他的components是不会被渲染的,会被自动忽略。FormPanel的最大用户在于,可以作为其添加的Fields的总管。可以通过设置FormPanel来影响其包含的所有的Fields components。比如设置只读属性,验证表单,Fields的显示状态,最后还包括表单的提交功能——HTTP POST提交和GWT RPC(稍后提到)。
Fields
对于具体的Fields的介绍,说实话GXT我也是探索中曲折前进。大家可以参看:http://www.sencha.com/examples/explorer.html#forms创建一个feed button
既然用户提出需求了,我们就要开始开发新的功能了。我们需要在RssNavigationPanel类中,添加一个button,来允许用户添加一个具体的feed信息。此次是实用的的Button,而不是ToggleButton。- 编辑RSSReader.css:加入如下的css样式,为了给“Create feed”button应用此样式。
.create-feed {
background: url(gxt/images/icons/feed_create.png) no-repeat center left
!important;
}
- RssNavigationPanel类构造函数中,继续加入“Create feed”button的定义。
final Button btnCreateFeed = new Button("Create feed");
btnCreateFeed.setIconStyle("create-feed");
ToolTipConfig createNewToolTipConfig = new ToolTipConfig();
createNewToolTipConfig.setTitle("Create a new RSS feed");
createNewToolTipConfig.setText("Creates a new RSS feed");
btnCreateFeed.setToolTip(createNewToolTipConfig);
addButton(btnCreateFeed);
addButton(btnLinkFeed);
- 运行程序,观看“Create feed”button的显示效果
创建一个Feed 类
创建一个用来存储feed信息的POJO类。之后他会通过Google RPC发送,所以要保证Feed类implements Serializable接口,并且有无参数的构造函数。Feed类既被client端使用,又会被Server端使用。因此,相对于client和server包,最好把他放在shared 包下更合适。那么shared包里的类,就会被client和server类共同调用。
在这里要重点说明一下,GWT不是会把项目里面所有的package都作为编译成javaScript的source 代码,而是通过module xml文件配置的(RSSReader.gwt.xml)。因此需要把shared包加入GWT的编译路径中去。
- 创建新包:com.danielvaughan.rssreader.shared.model
- 修改RSSReader.gwt.xml,加入另外一个GWT编译入口——shared package:
<!-- Specify the paths for translatable code -->
<source path='client'/>
<source path='shared'/>
- 如上配置,client就是指:com.danielvaughan.rssreader.client,shared就是指:com.danielvaughan.rssreader.shared,为什么GWT就就此翻译成此路径,我个人认为是RSSReader.gwt.xml配置文件存放在com.danielvaughan.rssreader包下的原因。
- 创建Feed类,放在com.danielvaughan.rssreader.shared.model下:
package com.danielvaughan.rssreader.shared.model;
import java.io.Serializable;
@SuppressWarnings("serial")
public class Feed implements Serializable {
private String description;
private String link;
private String title;
private String uuid;
public Feed() {
}
public Feed(String uuid) {
this.uuid = uuid;
}
public String getDescription() {
return description;
}
public String getLink() {
return link;
}
public String getTitle() {
return title;
}
public String getUuid() {
return uuid;
}
public void setDescription(String description) {
this.description = description;
}
public void setLink(String link) {
this.link = link;
}
public void setTitle(String title) {
this.title = title;
}
}
- 目前为止,整个项目RSSReader的项目结构如下: