最近发现oschina不给我发每周精彩回顾了,才想起距离上次写东西已经有9个月了,于是狠狠的惭愧了一把。程序员光干活,不总结是不行的,于是便跟大家分享下下面这些开发体验。
最近公司的外网项目,都准备用Gwt开发,经过之前的一些试验,公司决定采用SmartGwt 2.4作为前台框架。经过一段使用之后,感觉SmartGwt基本上比较容易上手。不过,虽然他的showcase的例子挺丰富,但只覆盖了很少的api,所以基本上还是天天翻着api来开发。
其组件库涵盖了绝大多数常见的控件,但是没有分页条,居然少了这么常用的组件,着实让人遗憾。先google了一下,没有令人满意的现成的扩展组件,查了半天,只在一个英文论坛里,发现一个半成品,只是个实现了部分页面展示逻辑的页面组件,而且没有数据交互。无奈,找不到现成的,只能自己动手丰衣足食了。
一、定义分页条功能
功能至少要满足基本需要。
比如对于用户来说,页面功能应该包括:
1、能够定位数据到:首页,上一页,下一页,末页
2、能够展示当前页和总页数
3、直接跳转到指定页(大于零,小于总页数)
4、根据当前页和总页数,控制按钮可用状态
对于程序员来说,这个组件应该可以:
1、方便的初始化工具条组件并能绑定数据展示组件(比如grid)
2、定制每页记录数
3、最好和数据查询方法分离,消除对业务查询方法的依赖
4、最好能有个模态遮罩,在数据加载过程中,给予提示,同时限制用户的重复操作。
二、代码实现
经过分析和简单的设计,决定通过两个类来实现:
1、一个纯页面组件,继承自com.smartgwt.client.widgets.toolbar.ToolStrip。代码实现思路就不写了,反正是从混沌到清晰的一个过程。直接帖代码了
001
<span class="Apple-style-span">import com.smartgwt.client.types.Alignment;
002
import com.smartgwt.client.types.Overflow;
003
import com.smartgwt.client.util.SC;
004
import com.smartgwt.client.widgets.Canvas;
005
import com.smartgwt.client.widgets.IButton;
006
import com.smartgwt.client.widgets.Label;
007
import com.smartgwt.client.widgets.events.ClickEvent;
008
import com.smartgwt.client.widgets.events.ClickHandler;
009
import com.smartgwt.client.widgets.form.DynamicForm;
010
import com.smartgwt.client.widgets.form.fields.TextItem;
011
import com.smartgwt.client.widgets.grid.ListGrid;
012
import com.smartgwt.client.widgets.grid.ListGridRecord;
013
import com.smartgwt.client.widgets.toolbar.ToolStrip;
014
015
/**
016
*
017
* 分页工具条
018
*
019
* 使用方法:
020
* 1、实例化一个分页工具栏,传入每页记录条数和绑定的grid
021
* 2、实现一个ListGridDataControl(实例化方法参见类中注释,注意和分页工具的相互调用),并把它设值给分页工具栏的dataControl属性,
022
* 注意:分页工具条和ListGridDataControl需要紧密配合相互调用。
023
* 3、调用active()方法,激活分页条并加载grid数据
024
*
025
* 提示:
026
* 1、本分页工具不处理grid的行号,行号理解为grid的列定义范畴
027
* 2、可以多次调用active()方法,调用的结果相当于把分页栏定位到首页,并重新获取总页数
028
* 3、如果查询业务数据的参数改变时,可以重新实现并设置ListGridDataControl,然后调用active()
029
* 4、可以调用setMaskMessage()设置遮罩的提示信息,如果不设置,采用默认值
030
*
031
* 说明:
032
* 之所以需要ListGridDataControl回调分页工具条的方法,导致增加了相互依赖,主要是考虑到获取数据和获取记录总数的方法通常是异步的,
033
* 为保持操作的同步性,只能通过互相调用的方式保持工具条和grid的正常工作。
034
*
035
* @author weichao
036
* @version 1.0
037
*/
038
public class GridPaginationBar extends ToolStrip{
039
040
/**
041
* 模态遮罩
042
*/
043
ModalWindow mask;
044
045
private String maskMessage = " 数据加载中...... ";
046
047
public void setMaskMessage(String maskMessage) {
048
this.maskMessage = maskMessage;
049
}
050
/**
051
* 每页条数
052
*/
053
private int pageSize = -1;
054
055
/**
056
* 当前页
057
*/
058
private int pageNum = -1;
059
060
/**
061
* 总页数
062
*/
063
private int totalPage = -1;
064
065
/**
066
* 数据记录条数
067
*/
068
private int totalRowNum = -1;
069
070
/**
071
* 绑定的grid
072
*/
073
private final ListGrid grid;
074
075
//首页</span><span class="Apple-style-span"> TopImgButton first = new TopImgButton(16,16,"/img/control_start_blue.png","/img/control_start.png");
076
077
//上一页
078
TopImgButton backward = new TopImgButton(16,16,"/img/control_rewind_blue.png","/img/control_rewind.png");
079
080
//下一页
081
TopImgButton forward = new TopImgButton(16,16,"/img/control_fastforward_blue.png","/img/control_fastforward.png");
082
083
//末页
084
TopImgButton last = new TopImgButton(16,16,"/img/control_end_blue.png","/img/control_end.png");
085
086
//输入框form
087
DynamicForm pageForm;
088
089
//页码输入框
090
protected TextItem pageText;
091
092
//转到按钮
093
IButton go = new IButton("转到");
094
095
//总页数
096
protected Label totalLabel;
097
098
//grid数据控制器
099
private ListGridDataControl dataControl;
100
101
public void setDataControl(ListGridDataControl dataControl){
102
this.dataControl = dataControl;
103
}
104
105
public GridPaginationBar(ListGrid listGrid, int pageSize) {
106
this(listGrid, pageSize,null);
107
}
108
109
/**
110
*
111
* 构造方法中,只初始化工具条元素和事件,不初始化数据,
112
* 构造完成后工具条处于禁用状态,需要首先传入grid数据控制器,
113
* 然后调用active()方法来激活工具条,并开始加载数据。
114
*
115
* @param listGrid 绑定的grid
116
* @param pageSize 每页记录条数
117
* @param maskCanvas 加载数据过程中,需要用遮罩遮盖的控件,如果传入null,则默认遮盖的对象为绑定的grid
118
*/
119
public GridPaginationBar(ListGrid listGrid, int pageSize, Canvas maskCanvas) {
120
this.grid = listGrid;
121
mask = new ModalWindow(maskCanvas == null ? grid : maskCanvas);
122
mask.setLoadingIcon("/img/loading.gif");
123
this.pageSize = pageSize;
124
first.setButtonTip("首页");
125
first.setButtonClickHandler(new ClickHandler(){
126
public void onClick(ClickEvent event) {
127
goToPage(1);
128
}
129
});
130
backward.setButtonTip("上一页");
131
backward.setButtonClickHandler(new ClickHandler(){
132
public void onClick(ClickEvent event){
133
goToPage(pageNum - 1);
134
}
135
});
136
pageText = new TextItem();
137
pageText.setWidth(40);
138
pageText.setHeight(20);
139
pageText.setShowTitle(false);
140
pageText.setTextAlign(Alignment.RIGHT);
141
go.setWidth(34);
142
go.setHeight(20);
143
go.addClickHandler(new ClickHandler(){
144
public void onClick(ClickEvent event) {
145
String page = pageText.getValueAsString();
146
if(page == null || page.trim().equals("")){
147
SC.say("请输入页码");
148
return ;
149
}else {
150
try{
151
int pageint = Integer.valueOf(page);
152
if(pageint<1){
153
SC.say("输入的页码不能小于1");
154
return;
155
}else if(pageint>totalPage){
156
SC.say("输入的页码不能大于总页数 "+totalPage);
157
return;
158
}else {
159
goToPage(pageint);
160
}
161
}catch(NumberFormatException e){
162
SC.say("请输入整数");
163
return;
164
}
165
}
166
}});
167
168
forward.setButtonTip("下一页");
169
forward.setButtonClickHandler(new ClickHandler(){
170
public void onClick(ClickEvent event){
171
goToPage(pageNum + 1);
172
}
173
});
174
175
last.setButtonTip("末页");
176
last.setButtonClickHandler(new ClickHandler(){
177
public void onClick(ClickEvent event){
178
goToPage(totalPage);
179
}
180
});
181
182
totalLabel = new Label();
183
totalLabel.setWrap(false);
184
totalLabel.setWidth(50);
185
186
setHeight(20);
187
setOverflow(Overflow.VISIBLE);
188
setStyleName("normal");
189
this.setMargin(5);
190
191
pageForm = new DynamicForm();
192
pageForm.setNumCols(1);
193
pageForm.setWidth(45);
194
pageForm.setItems(pageText);
195
Label blank1 = new Label();
196
blank1.setContents(" ");
197
blank1.setWidth(5);
198
blank1.setHeight(20);
199
200
Label blank2 = new Label();
201
blank2.setContents(" ");
202
blank2.setWidth(5);
203
blank2.setHeight(20);
204
205
Label blank3 = new Label();
206
blank3.setContents(" ");
207
blank3.setWidth(15);
208
blank3.setHeight(20);
209
210
Label blank4 = new Label();
211
blank4.setContents(" ");
212
blank4.setWidth(5);
213
blank4.setHeight(20);
214
215
Label blank5 = new Label();
216
blank5.setContents(" ");
217
blank5.setWidth(5);
218
blank5.setHeight(20);
219
220
addMember(first);
221
addMember(blank1);
222
addMember(backward);
223
addMember(blank2);
224
addMember(pageForm);
225
addMember(go);
226
addMember(blank5);
227
addMember(forward);
228
addMember(blank4);
229
addMember(last);
230
addMember(blank3);
231
addMember(totalLabel);
232
setAlign(Alignment.RIGHT);
233
resetPaginationState();
234
}
235
236
/**
237
* 转到指定页,获取分页数据并装载,
238
* 获取数据过程中,加模态遮罩
239
*
240
* @param pageNum
241
*/
242
public void goToPage(int pageNum) {
243
go.disable();
244
if (pageNum > totalPage)
245
pageNum = totalPage;
246
if (pageNum < 1)
247
pageNum = 1;
248
if (pageNum == this.pageNum) {
249
go.enable();
250
return;
251
}
252
mask.show(maskMessage, true);
253
//fetch data and reload grid
254
this.pageNum = pageNum;
255
int startNum = (pageNum - 1) * pageSize;
256
dataControl.fetchData(startNum, pageSize);
257
}
258
259
/**
260
* 根据记录总数计算总页数
261
*/
262
private void countTotalPages()
263
{
264
if(totalRowNum < 1){
265
totalPage = -1;
266
return;
267
}
268
int pages = (int) Math.ceil(((float) totalRowNum) / ((float) pageSize));
269
// never return zero pages
270
if (pages == 0)
271
pages = 1;
272
this.totalPage=pages;
273
pageNum = 1;
274
}
275
276
/**
277
* 首次查询数据,获取数据总数等信息,并更新分页条状态
278
* 获取数据过程中,加模态遮罩
279
*/
280
public void active(){
281
if(dataControl == null){
282
SC.say("错误","分页栏未配置ListGridDataControl数据控制器,请检查代码");
283
return;
284
}
285
//首先禁用工具条
286
if(pageNum != -1){
287
resetPaginationState();
288
}
289
mask.show(maskMessage, true);
290
dataControl.getTotal();
291
}
292
293
/**
294
* ListGridDataControl获取总记录数后的回调方法
295
* @param all
296
*/
297
public void afterGetTotal(int all){
298
this.totalRowNum = all;
299
countTotalPages();
300
if(totalPage==-1){
301
//如果没有查询到数据,则清空原来的数据
302
afterFetchData(new ListGridRecord[0]);
303
} else {
304
dataControl.fetchData(0, pageSize);
305
}
306
}
307
308
/**
309
* ListGridDataControl获取数据后的回调方法
310
* @param datas
311
*/
312
public void afterFetchData(ListGridRecord[] datas){
313
if(datas != null){
314
dataControl.loadData(datas);
315
}
316
updatePageinationState();
317
mask.hide();
318
}
319
320
/**
321
* 清除分页工具条状态,全部置灰,不负责清空grid当前数据
322
*/
323
private void resetPaginationState(){
324
pageNum = -1;
325
totalPage = -1;
326
totalRowNum = -1;
327
first.disable();
328
backward.disable();
329
last.disable();
330
forward.disable();
331
pageText.disable();
332
go.disable();
333
totalLabel.setContents("");
334
}
335
336
/**
337
* 依据当前页和总页数控制工具条状态
338
* 规则:
339
* 当前页为-1,则说明工具条尚未激活或者没有查询到数据,不需要处理;
340
* 当前页等于1,则首页按钮和上一页按钮置灰,否则,激活;
341
* 当前页等于总页数,则末页按钮和上一页按钮置灰,否则,激活;
342
*/
343
private void updatePageinationState() {
344
if(pageNum==-1||totalPage==-1){
345
return;
346
}
347
totalLabel.setContents("第" + pageNum + "页/共" + totalPage + "页");
348
pageText.enable();
349
go.enable();
350
pageText.setValue(pageNum);
351
if (pageNum == 1){
352
first.disable();
353
backward.disable();
354
} else {
355
first.enable();
356
backward.enable();
357
}
358
if (pageNum == totalPage){
359
last.disable();
360
forward.disable();
361
} else {
362
last.enable();
363
forward.enable();
364
}
365
}
366
}</span>
2、一个控制接口类
即GridPaginationBar 类里的ListGridDataControl ,代码如下:
01
import com.smartgwt.client.widgets.grid.ListGridRecord;
02
03
/**
04
*
05
* @author weichao
06
* listGrid数据获取及装载接口 ,和工具条有紧密的相互调用
07
* grid加分页工具条时,需要实现此接口并提供给分页工具条
08
*
09
*
10
* 示例:
11
*
12
* GridPaginationBar pageBar = new GridPaginationBar(bizGrid,20,bizGrid.getParentElement());
13
*
14
* pageBar.setDataControl(new ListGridDataControl(){
15
* public void fetchData(int start, int pageSize) {
16
* service.getBusiness(sid,start,pageSize,
17
* new AsyncCallback<List<XXXXXVO>>() {
18
* public void onFailure(Throwable caught) {
19
* Window.alert(caught.getMessage());
20
* }
21
* public void onSuccess(List<XXXXXVO> result) {
22
* list = result;
23
* pageBar.afterFetchData(RenderBizData.getNewRecords(result));
24
* }
25
* });
26
* }
27
* public void getTotal() {
28
* service.getBusinessTotal(sid, new AsyncCallback<Integer>(){
29
* public void onFailure(Throwable arg0) {
30
* Window.alert(arg0.getMessage());
31
* }
32
* public void onSuccess(Integer arg0) {
33
* pageBar.afterGetTotal(arg0);
34
* }} );
35
* }
36
* public void loadData(ListGridRecord[] records) {
37
* bizGrid.setData(records);
38
* }});
39
*/
40
public interface ListGridDataControl {
41
42
/**
43
* 获取分页数据,并回调分页工具栏的afterFetchData()方法,
44
* 如果需要异步获取数据,请注意回调afterFetchData()的时机,保持数据的同步操作。
45
*
46
* @param start
47
* @param pageSize
48
*/
49
public void fetchData(int start,int pageSize);
50
51
/**
52
* 获取数据记录总数,并回调分页工具栏的afterGetTotal()方法
53
* 如果需要异步获取数据,请注意回调afterGetTotal()的时机,保持数据的同步操作。
54
*
55
* @return 总数
56
*/
57
public void getTotal();
58
59
/**
60
* 把数据装载入grid
61
* @param records
62
*/
63
public void loadData(ListGridRecord[] records);
64
}
3、从网上找了个模态窗口ModalWindow ,直接使用了,这里就不贴代码了:
需要的可以从这里找
http://code.google.com/p/smartgwt-extensions/source/browse/trunk/mainprojects/src/main/java/com/smartgwt/extensions#extensions%2Fmodal%2Fclient%253Fstate%253Dclosed
4、TopImgButton类是自己实现的一个按钮类,当然你可以用smartgwt的按钮 ,或者你自己写个。
01
import com.smartgwt.client.types.Cursor;
02
import com.smartgwt.client.widgets.Img;
03
import com.smartgwt.client.widgets.events.ClickHandler;
04
import com.smartgwt.client.widgets.layout.HLayout;
05
06
/**
07
* @author weichao
08
* 有激活和置灰两种状态的图片按钮
09
*/
10
public class TopImgButton extends HLayout{
11
Img enable = new Img();
12
Img disable = new Img();
13
private boolean _enable = true;
14
public TopImgButton(int buttonWidth,int buttonHeight,String enableImgSrc,String disableImgSrc){
15
setWidth(buttonWidth);
16
setHeight(buttonHeight);
17
enable.setSrc(enableImgSrc);
18
enable.setWidth(buttonWidth);
19
enable.setHeight(buttonHeight);
20
enable.setCursor(Cursor.POINTER);
21
disable.setSrc(disableImgSrc);
22
disable.setWidth(buttonWidth);
23
disable.setHeight(buttonHeight);
24
addMember(enable);
25
}
26
27
public void enable(){
28
if(!_enable){
29
removeMember(disable);
30
addMember(enable);
31
_enable = !_enable;
32
}
33
}
34
35
public void disable(){
36
if(_enable){
37
removeMember(enable);
38
addMember(disable);
39
_enable = !_enable;
40
}
41
}
42
43
public void setButtonClickHandler(ClickHandler handler){
44
enable.addClickHandler(handler);
45
}
46
47
public void setButtonTip(String tipMessage){
48
enable.setTooltip(tipMessage);
49
}
50
}
三、效果
注释里写的比较多了,还有示例也帖在类的注释里了,所以就不再解释怎么用了。
经过几番测试,感觉运行比较稳定。希望能对需要smartgwt分页的朋友有所帮助。
基于SmartGwt的分页组件
最新推荐文章于 2021-04-17 22:24:25 发布