前面介紹了關于JTable的基本使用、JTable單元格的Renderer和Editor、JTable的單元格的合并和拆分、JTableHeader的Renderer和Editor、JTableHeader的的合并和拆分等.現在介紹一種關于JTable表現的情況,比如我們從DB或者文件中取得數據之后,我們把它插入JTable之中時,我們是想知道它的行號的,但是我們排序之后行號是不應該變化的,這樣我們就不能把行號的數據和JTable的數據放置在一個Model中(當然也是有辦法的,比如我們重寫TableModel,當數據改變時,我們重寫FireTableChange方法更改數據行號,但是很復雜.)
我們一般的做法是設置另外一個JTable,重寫tableChanged和propertyChange,監聽主JTable的變化,當主JTable的數據變化時,我們同時也更新這個行號JTable的數據,這個就可以達到JTable的數據改變時我們行號JTable的數據也隨之改變.
先看看完成的效果:
排序后,行號是不變的:
然后哦就是我們的實現了,先看行號那一列的類,先實現它的TableModel,
/**
*createtherowtablemodel.
*/
privateclass RowHeaderModel extends AbstractTableModel
{
這個行JTable的TableModel是和數據JTable是關聯的,我們根據數據的JTable的Model調整這個行JTable.
先是構造函數,很簡單,只需要傳入數據JTable的Model.
public RowHeaderModel(TableModel model) {
this.model = model;
}
接下來是TableModel的方法的復寫:
@Override
publicint getColumnCount() {
return 1;
}
只有一列數據.
@Override
publicint getRowCount() {
returnmodel.getRowCount();
}
行數和數據JTable的行號一樣.
@Override
public String getColumnName(int col) {
return"";
}
不顯示表頭.
@Override
publicboolean isCellEditable(int row, int column) {
returnfalse;
}
設置為不可編輯的.
然后就是行號JTable的單元格的表現了,我們繼承TableCellRenderer,使它返回行號.
/**
*createtablecellrenderer.
*/
privateclass RowHeaderRenderer extends JButton implements
TableCellRenderer {
復寫getInsets使JTable的單元格沒有間隙
@Override
public Insets getInsets() {
returnnew Insets(0, 0, 0, 0);
}
然后是實現TableCellRenderer的方法:
@Override
public Component getTableCellRendererComponent(JTable table,
Object
value, boolean isSelected, boolean hasFocus, int row, int column) {
// set cell text
this.setText("" + (row +
1));
設置行號就可以了.
然后就是行號JTable這個類了
/**
*createtherowtable.
*/
publicclass RowTable extends JTable {
實現很簡單,因為JTable的Model和Rnederer已經完成了,不需要再設置數據了:
初始化設置Model和Renderer就可以了:
setModel(new RowHeaderModel(table.getModel()));
setRowHeight(table.getRowHeight());
getColumn("").setCellRenderer(new
RowHeaderRenderer());
這樣行號JTable就完成了,現在我們需要實現一個類繼承JscrollPane,當我們需要創建JTable時,只需要根據我們的JTable創建行號JTable,然后把兩個JTable放置在我們自己的JscrollPane之中就可以了.
/**
*RowtableScrollPane.
*/
publicclass RowTableScrollPane extends JScrollPane implements
PropertyChangeListener,
TableModelListener {
它繼承JscrollPane實現PropertyChangeListener和TableModelListener接口,當數據JTable變化時,我們同時更新行號JTable的數據.
先看屬性,很簡單,需要放置的兩個JTable:
// row table
protected RowTable rowHeader = null;
// data table
protected JTable table = null;
構造函數也很簡單,只需要傳入我們的數據JTable
/**
*
*/
public RowTableScrollPane(JTable table) {
if (table == null) {
thrownew IllegalArgumentException("table is null");
}
this.table = table;
然后初始化時構造行號JTable,設置監聽:
table.addPropertyChangeListener(this);
table.getModel().addTableModelListener(this);
rowHeader = new RowTable(table);
放置在JscrollPane上面:
setViewportView(table);
setRowHeaderView(rowHeader);
響應數據JTable的事件,當數據JTable變化時,同時更新行號JTable:
@Override
publicvoid propertyChange(PropertyChangeEvent e) {
if (rowHeader != null) {
rowHeader.setTableModel(table);
}
}
@Override
publicvoid tableChanged(TableModelEvent e) {
if (rowHeader != null) {
rowHeader.setTableModel(table);
}
}
最后就是使用了,它的使用也很簡單,原本我們創建好JTable之后使用JscrollPane變現JTable:
//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
現在只需要把JscrollPane換成我們自己實現的RowTableScrollPane就可以了:
RowTableScrollPane scrollPane = new RowTableScrollPane(table);
這樣實現出來的JTable就自動添加上表格了.
最后再補充一點,我們可以不使用JTable作為行號的那一列,使用一個Jlist也可以了,如下圖:
實現方法也一樣,只需要實現Jlist的ListModel時和JTable的Model關聯就可以了,和前面介紹的JTable的例子一樣,把它們都放置在JscrollPane之上關聯PropertyChangeListener和TableModelListener事件就可以了,就不詳細介紹了,自此當然我們也可以聯想到別的組件,只要我們可以實現一個組件的Model具有和JTable的數據關聯的特性,就可以作出另外的效果了.
到這里為止,關于JTable的除了拖拽就算是完了,以后想到新的再補充了,下個開始寫JTree的,以后要寫ExtJS了,估計時間會少很多了.