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