TWaver Java不但提供了TTable、TElementTable這些表格組件,而且還提供了表格翻頁器TPageNavigator。讓表格和翻頁器結(jié)合工作,可以立刻做出一個(gè)非常標(biāo)準(zhǔn)的可翻頁
的表格界面,如下圖。
要讓這兩個(gè)組件一起工作,直接這樣new一個(gè)實(shí)例,并放在界面上就可以了:
1 TElementTable table = new TElementTable();
2 int[] pageSizes = { 100, 500, 1000 };
3 TPageNavigator nav=new TPageNavigator(table.getTablePaging(), pageSizes)
其中nav就是一個(gè)普通的JPanel,可以放在界面的任何位置。而table可以和nav在界面上完全脫離顯示,如何布局都可以。
不過,這個(gè)可以翻頁的表格,只能翻頁本地?cái)?shù)據(jù)。也就是說,它只能翻已經(jīng)放入TDataBox中的數(shù)據(jù)。例如我們一次性在TDataBox中加入了10000條數(shù)據(jù),可以通過這個(gè)
翻頁器進(jìn)行“每頁100條、共有100頁”這樣的翻頁操作。但是大多時(shí)候,我們需要的并不是“本地翻頁”,而是“遠(yuǎn)程翻頁”。所謂的遠(yuǎn)程翻頁,也就是在每次翻頁時(shí)候,
TDataBox的數(shù)據(jù)需要被清空,并從遠(yuǎn)程服務(wù)器動(dòng)態(tài)重新獲取“下一頁”的數(shù)據(jù)進(jìn)行TDataBox加載并且顯示。
如何做到這一點(diǎn)呢?只要用了TWaver Java這一“神器”,做到這一點(diǎn)就不難了。本文就通過一個(gè)例子,來說明如何定制一個(gè)翻頁器,來攔截翻頁動(dòng)作,并從服務(wù)器獲取
翻頁數(shù)據(jù),進(jìn)行動(dòng)態(tài)顯示。
TElementTable的翻頁,實(shí)際上是靠一個(gè)TablePaging的接口來完成的。TWaver Java靠一個(gè)默認(rèn)的TablePaging實(shí)現(xiàn)來完成了本地翻頁。
而我們要做的,就是創(chuàng)建一個(gè)遠(yuǎn)程翻頁的TablePaging,來代替這個(gè)默認(rèn)實(shí)現(xiàn)即可。
TablePaging接口定義了下面這些函數(shù)。大多數(shù)的函數(shù),都是在問你一些簡單的遠(yuǎn)端數(shù)據(jù)方面的問題:一共有多少記錄?一頁有多少條記錄?一共有多少頁?當(dāng)前是第幾頁?
并且在第一頁、最后一頁、上一頁、下一頁等操作發(fā)生時(shí),回調(diào)這個(gè)接口。所以,我們只要有了后臺(tái)數(shù)據(jù),就不難回答這些問題。
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 }
以上函數(shù)基本上都可以顧名思義地理解,就不多作介紹了。我們現(xiàn)在假設(shè)后臺(tái)有一個(gè)數(shù)據(jù)庫,里面有一個(gè)客戶地址的table。通過一個(gè)SQL查詢服務(wù),我們可以獲得這些翻頁數(shù)據(jù)。根據(jù)
這個(gè)假設(shè),我們可以做下面的實(shí)現(xiàn):
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 }
在上面代碼中,所有的翻頁函數(shù),都會(huì)集中調(diào)用loadPage()這個(gè)函數(shù),從后臺(tái)真正獲取數(shù)據(jù)。而函數(shù)getTotalRowCount則負(fù)責(zé)
從后臺(tái)獲得“一共有多少條記錄”。其他函數(shù),基本進(jìn)行轉(zhuǎn)發(fā)即可。
另外一個(gè)需要注意的就是removePageListener/addPageListener等函數(shù)。主要用于對監(jiān)聽器進(jìn)行管理,包括注冊、刪除、觸發(fā)通知等等。
這些也是必須要實(shí)現(xiàn)的,不過很簡單,用一個(gè)ArrayList維護(hù)就行了,觸發(fā)時(shí)間時(shí)候,直接遍歷、回調(diào)即可。
具體通過SQL從后臺(tái)調(diào)用數(shù)據(jù)的實(shí)現(xiàn),這里就不介紹了。相信每一個(gè)實(shí)際項(xiàng)目都有不同的數(shù)據(jù)庫、接口、調(diào)用方法方面的差別。這里只是點(diǎn)到為止。
有了這個(gè)翻頁器,我們就可以直接用在表格中了。下面繼承一個(gè)表格,并用這個(gè)翻頁器。
1 public class AddressTable extends TElementTable {
2
3 public AddressTablePaging getTablePaging() {
4 return tablePaging;
5 }
6
7 }
8
這樣,默認(rèn)翻頁器被替換,新的后臺(tái)翻頁器被置入表格中。最后,再通過本文最開始提供的兩行代碼把表格放入界面中,程序就基本完成了。
1 int[] pageSizes = { 100, 500, 1000 };
2 this.add(new TPageNavigator(table.getTablePaging(), pageSizes), BorderLayout.CENTER);
其中pageSizes數(shù)組是定義了界面上每頁條數(shù)的下拉列表選項(xiàng),我們可以根據(jù)實(shí)際應(yīng)用自己設(shè)置,如下圖:
這樣,一個(gè)完整的后臺(tái)翻頁程序就完成了。給表格設(shè)置好列、在后臺(tái)添加一些數(shù)據(jù),跑起來會(huì)是這樣:
如果再增加一些查詢字段等,就更帥了:

對了,最后,再順便給大家介紹一下表格中的可點(diǎn)擊連接是如何做的:
要做這種可點(diǎn)擊鏈接,首先要做3件事:1是顯示link,2是顯示手形狀的光標(biāo),3是響應(yīng)鼠標(biāo)點(diǎn)擊動(dòng)作。對于1,可以來個(gè)“釜底抽薪”:在表格上從根兒上攔截prepareRenderer
然后對文字動(dòng)態(tài)修改為html的a標(biāo)簽的連接方式進(jìn)行處理:
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
對于手形光標(biāo),可以通過監(jiān)聽鼠標(biāo)移動(dòng),是否位于鏈接文字上方來動(dòng)態(tài)修改光標(biāo):
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 });
最后,對于點(diǎn)擊動(dòng)作,可以通過給table添加鼠標(biāo)監(jiān)聽器完成:
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
至此,一個(gè)完整的可后臺(tái)翻頁、可鼠標(biāo)點(diǎn)擊超鏈接的綜合型table就完成了。在實(shí)際使用中,還可以增加更復(fù)雜的翻頁和
顯示效果。例如在TWaver的兄弟產(chǎn)品2BizBox免費(fèi)ERP軟件中,就有大量這樣的應(yīng)用,感興趣的朋友可以到2BizBox.cn
去下載安裝一個(gè)玩一玩。