前面介绍了关于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了,估计时间会少很多了.