TWaver - 专注UI技术

http://twaver.servasoft.com/
posts - 171, comments - 191, trackbacks - 0, articles - 2
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

让Swing表格支持远程后台数据翻页

Posted on 2012-08-03 17:23 TWaver 阅读(1676) 评论(0)  编辑  收藏
TWaver Java不但提供了TTable、TElementTable这些表格组件,而且还提供了表格翻页器TPageNavigator。让表格和翻页器结合工作,可以立刻做出一个非常标准的可翻页
的表格界面,如下图。

要让这两个组件一起工作,直接这样new一个实例,并放在界面上就可以了:

1 TElementTable table = new TElementTable();
2 int[] pageSizes = { 100, 500, 1000 };
3 TPageNavigator nav=new TPageNavigator(table.getTablePaging(), pageSizes)

其中nav就是一个普通的JPanel,可以放在界面的任何位置。而table可以和nav在界面上完全脱离显示,如何布局都可以。

不过,这个可以翻页的表格,只能翻页本地数据。也就是说,它只能翻已经放入TDataBox中的数据。例如我们一次性在TDataBox中加入了10000条数据,可以通过这个
翻页器进行“每页100条、共有100页”这样的翻页操作。但是大多时候,我们需要的并不是“本地翻页”,而是“远程翻页”。所谓的远程翻页,也就是在每次翻页时候,
TDataBox的数据需要被清空,并从远程服务器动态重新获取“下一页”的数据进行TDataBox加载并且显示。

如何做到这一点呢?只要用了TWaver Java这一“神器”,做到这一点就不难了。本文就通过一个例子,来说明如何定制一个翻页器,来拦截翻页动作,并从服务器获取
翻页数据,进行动态显示。

TElementTable的翻页,实际上是靠一个TablePaging的接口来完成的。TWaver Java靠一个默认的TablePaging实现来完成了本地翻页。
而我们要做的,就是创建一个远程翻页的TablePaging,来代替这个默认实现即可。

TablePaging接口定义了下面这些函数。大多数的函数,都是在问你一些简单的远端数据方面的问题:一共有多少记录?一页有多少条记录?一共有多少页?当前是第几页?
并且在第一页、最后一页、上一页、下一页等操作发生时,回调这个接口。所以,我们只要有了后台数据,就不难回答这些问题。

 1 public interface TablePaging {
 2     public int getCurrentPageIndex();
 3     public void setCurrentPageIndex(int currentPageIndex);
 4     public int getPageRowSize();
 5     public void setPageRowSize(int pageRowSize);
 6     public int getPageTotalCount();
 7     public int getTotalRowCount();
 8     public void firstPage();
 9     public void previousPage();
10     public void nextPage();
11     public void lastPage();
12     public void update();
13     public void addPageListener(PageListener pageListener);
14     public void removePageListener(PageListener pageListener);
15 }

 以上函数基本上都可以顾名思义地理解,就不多作介绍了。我们现在假设后台有一个数据库,里面有一个客户地址的table。通过一个SQL查询服务,我们可以获得这些翻页数据。根据
这个假设,我们可以做下面的实现:

  1 public class AddressTablePaging implements TablePaging {
  2     private SearchPane parent = null;
  3     private List pageListeners = new ArrayList();
  4     private TElementTable table = null;
  5     private int pageIndex = 1;
  6     private int pageSize = 100;
  7 
  8     public AddressTablePaging(TElementTable table, SearchPane parent) {
  9         this.table = table;
 10         this.parent = parent;
 11     }
 12 
 13     private void loadPage() {
 14         table.getDataBox().clear();
 15         try {
 16             int start = (pageIndex - 1) * pageSize;
 17             Collection<AddressVO> data = Server.searchAddress(..);
 18             for (AddressVO vo : data) {
 19                 Node node = new Node();
 20                 node.setBusinessObject(vo);
 21                 table.getDataBox().addElement(node);
 22             }
 23         } catch (Exception ex) {
 24             ex.printStackTrace();
 25             JOptionPane.showMessageDialog(table, ex.getMessage());
 26         }
 27         firePageChanged();
 28     }
 29 
 30     @Override
 31     public void firstPage() {
 32         pageIndex = 1;
 33         loadPage();
 34     }
 35 
 36     @Override
 37     public int getCurrentPageIndex() {
 38         return this.pageIndex;
 39     }
 40 
 41     @Override
 42     public int getPageRowSize() {
 43         return this.pageSize;
 44     }
 45 
 46     @Override
 47     public int getPageTotalCount() {
 48         try {
 49             int totalCount = getTotalRowCount();
 50             int pageCount = totalCount / getPageRowSize();
 51             if (totalCount % getPageRowSize() > 0) {
 52                 pageCount++;
 53             }
 54             return pageCount;
 55         } catch (Exception ex) {
 56             ex.printStackTrace();
 57         }
 58         return 0;
 59     }
 60 
 61     @Override
 62     public int getTotalRowCount() {
 63         try {
 64             return Server.getAddressTotalCount(.);
 65         } catch (Exception ex) {
 66             ex.printStackTrace();
 67         }
 68         return 0;
 69     }
 70 
 71     @Override
 72     public void lastPage() {
 73         this.pageIndex = getPageTotalCount();
 74         this.loadPage();
 75     }
 76 
 77     @Override
 78     public void nextPage() {
 79         this.pageIndex++;
 80         this.loadPage();
 81     }
 82 
 83     @Override
 84     public void previousPage() {
 85         if (this.pageIndex > 1) {
 86             pageIndex--;
 87         }
 88         this.loadPage();
 89     }
 90 
 91     @Override
 92     public void setCurrentPageIndex(int pageIndex) {
 93         this.pageIndex = pageIndex;
 94     }
 95 
 96     @Override
 97     public void setPageRowSize(int pageSize) {
 98         this.pageSize = pageSize;
 99     }
100 
101     @Override
102     public void addPageListener(PageListener pageListener) {
103         this.pageListeners.add(pageListener);
104     }
105 
106     @Override
107     public void removePageListener(PageListener pageListener) {
108         this.pageListeners.remove(pageListener);
109     }
110 
111     public void firePageChanged() {
112         for (int i = 0; i < this.pageListeners.size(); i++) {
113             PageListener pageListener = (PageListener) this.pageListeners.get(i);
114             pageListener.pageChanged();
115         }
116     }
117 
118     @Override
119     public void update() {
120     }
121 }

 在上面代码中,所有的翻页函数,都会集中调用loadPage()这个函数,从后台真正获取数据。而函数getTotalRowCount则负责
从后台获得“一共有多少条记录”。其他函数,基本进行转发即可。

另外一个需要注意的就是removePageListener/addPageListener等函数。主要用于对监听器进行管理,包括注册、删除、触发通知等等。
这些也是必须要实现的,不过很简单,用一个ArrayList维护就行了,触发时间时候,直接遍历、回调即可。

具体通过SQL从后台调用数据的实现,这里就不介绍了。相信每一个实际项目都有不同的数据库、接口、调用方法方面的差别。这里只是点到为止。

有了这个翻页器,我们就可以直接用在表格中了。下面继承一个表格,并用这个翻页器。

1 public class AddressTable extends TElementTable {
2     
3     public AddressTablePaging getTablePaging() {
4         return tablePaging;
5     }
6     
7 }
8 

这样,默认翻页器被替换,新的后台翻页器被置入表格中。最后,再通过本文最开始提供的两行代码把表格放入界面中,程序就基本完成了。

1 int[] pageSizes = { 100, 500, 1000 };
2 this.add(new TPageNavigator(table.getTablePaging(), pageSizes), BorderLayout.CENTER);

其中pageSizes数组是定义了界面上每页条数的下拉列表选项,我们可以根据实际应用自己设置,如下图:

这样,一个完整的后台翻页程序就完成了。给表格设置好列、在后台添加一些数据,跑起来会是这样:



如果再增加一些查询字段等,就更帅了:

对了,最后,再顺便给大家介绍一下表格中的可点击连接是如何做的:


要做这种可点击链接,首先要做3件事:1是显示link,2是显示手形状的光标,3是响应鼠标点击动作。对于1,可以来个“釜底抽薪”:在表格上从根儿上拦截prepareRenderer
然后对文字动态修改为html的a标签的连接方式进行处理:

 1 @Override
 2 public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
 3     Element element = this.getElementByRowIndex(row);
 4     AddressVO vo = (AddressVO) element.getBusinessObject();
 5     Component com = super.prepareRenderer(renderer, row, column);
 6     if (!vo.isValid()) {
 7         com.setForeground(Color.red);
 8     } else {
 9         com.setForeground(Color.black);
10     }
11 
12     if (column == 2 || column == 3) {
13         String text = ((JLabel) com).getText();
14         text = "<html><a href=\"#\">" + text + "</a></html>";
15         ((JLabel) com).setText(text);
16     }
17     return com;
18 }
19 

 对于手形光标,可以通过监听鼠标移动,是否位于链接文字上方来动态修改光标:
 1 this.addMouseMotionListener(new MouseMotionAdapter() {
 2     @Override
 3     public void mouseMoved(MouseEvent e) {
 4         int row = rowAtPoint(e.getPoint());
 5         int column = columnAtPoint(e.getPoint());
 6         setCursor(Cursor.getDefaultCursor());
 7         if (row >= 0 && column >= 0) {
 8             if (column == 2 || column == 3) {
 9                 setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
10             }
11         }
12     }
13 });

最后,对于点击动作,可以通过给table添加鼠标监听器完成:
 1 this.addMouseListener(new MouseAdapter() {
 2     @Override
 3     public void mouseClicked(MouseEvent e) {
 4         int row = rowAtPoint(e.getPoint());
 5         int column = columnAtPoint(e.getPoint());
 6         setCursor(Cursor.getDefaultCursor());
 7         if (row >= 0 && column >= 0) {
 8             if (column == 2 || column == 3) {
 9                 Object value = getValueAt(row, column);
10                 //do your action here.
11             }
12         }
13     }
14 });
15 

至此,一个完整的可后台翻页、可鼠标点击超链接的综合型table就完成了。在实际使用中,还可以增加更复杂的翻页和
显示效果。例如在TWaver的兄弟产品2BizBox免费ERP软件中,就有大量这样的应用,感兴趣的朋友可以到2BizBox.cn
去下载安装一个玩一玩。


只有注册用户登录后才能发表评论。


网站导航: