1.什么是Row Header?
先来了解什么是Column Header. 打开Excel, 位于表格列上方,标有A,B,C,D...的地方就叫Column Header. 那Row Header就是左方标有行号的地方了.
2.为什么要为JTable加Row Header?
Swing中的JTable提供了强大的表格处理能力, 但只提供了Column Header功能,却没有直接提供加Row Header功能.
3.如何实现?
要想为JTable加上Row Header或Column Header, 要先将JTable放入一个JScrollPane. 我们先来看看JScrollPane的结构:
如图所示,JScrollPane有9个部分组成,我们可以用JScrollPane的以下这些方法,为这9个区域加上不同的组件:
setColumnHeaderView(Component view)
setCorner(String key, Component corner)
setHorizontalScrollBar(JScrollBar horizontalScrollBar)
setRowHeaderView(Component view)
setVerticalScrollBar(JScrollBar verticalScrollBar)
setViewportView(Component view)
其中有些方法的参数是Component,而几乎所有的swing组件都是由Component继承而来的,也就是说,我们可以为这些区域加上任意的swing组件.
再看如下代码:
public class ScrollableTable extends JFrame
{
public ScrollableTable()
{
JScrollPane scrollPane = new JScrollPane(new JTable(10,10));
this.getContentPane().add(scrollPane);
}
}
这个类将一个10*10单元格大小的Table加入了JScrollPane中,即图中的JViewPort的位置放置JTable,并且自动会为JTable加上Column Header,这个是Swing为我们自动完成的,我们只告诉它JTable加入了JScrollPane,ColumnHeader是它自动加上的.
要想为JTable加上row header实际上是为JScrollPane的Row Header区域加上一个类似于row header的东东.那什么组件最适于充当row header呢? 还是JTable! 对.我们再放一个JTable在JScrollPane的Row Header区域,让其行数与JViewPort中的JTable一样,并显示每一行的行号.如下:
DefaultTableModel model = new DefaultTableModel(50,10);
DefaultTableModel rowheadmodel = new DefaultTableModel(50,10);
JTable table = new JTable(model);
JTable rowHeaderTable = new JTable(rowheadmodel);
rowheadmodel.setColumnCount(1);
rowheadmodel.setColumnIdentifiers(new Object[]{""});
rowHeaderTable.setEnabled(false);
rowHeaderTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
rowHeaderTable.getColumnModel().getColumn(0).setPreferredWidth(50);
/*为rowHeaderTable设置预设的绘制器*/
rowHeaderTable.setDefaultRenderer(rowHeaderTable.getColumnClass(0),new RowHeaderRenderer(table));
rowHeaderTable.setPreferredScrollableViewportSize (
new Dimension
(
rowHeaderTable.getColumnModel().getColumn(0).getPreferredWidth()
,0
)
);
/*将table加入JScrollPane*/
JScrollPane scrollPane = new JScrollPane(table);
/*将rowHeaderTable作为row header加入JScrollPane的RowHeaderView区域*/
scrollPane.setRowHeaderView(rowHeaderTable);
this.getContentPane().add(scrollPane);
大家发现没有,在代码中有一个RowHeaderRenderer类(标为蓝色字体的),这个类是做什么的呢? 为了实现在table中新增、删除行时,rowHeaderTable的行数与行号一起变化,也为了Row Header看起来更像Header,我们实现了一个TableCellRenderer,用JLabel作为单元格的绘制器,并用:
public class RowHeaderRenderer extends JLabel implements TableCellRenderer
{
JTable reftable;
public RowHeaderRenderer(JTable reftable)
{
this.reftable = reftable;
}
public Component getTableCellRendererComponent(JTable table,
Object obj,
boolean isSelected,
boolean hasFocus,
int row, int col)
{
((DefaultTableModel)table.getModel()).setRowCount(reftable.getRowCount());
JTableHeader header = reftable.getTableHeader();
this.setOpaque(true);
/*设为TableHeader的边框类型*/
setBorder(UIManager.getBorder("TableHeader.cellBorder"));
setHorizontalAlignment(CENTER);
/*设置背景色为TableHeader的背景色*/
setBackground(header.getBackground());
Font font = header.getFont();
if ( isSelect(row) ) /* 当选取单元格时,在row header上设置成选取颜色 */
{
setForeground(Color.white);
setBackground(Color.lightGray);
setFont(font);
setText(String.valueOf(row+1));
}
else
{
setForeground(header.getForeground());
setFont(font);
setText(String.valueOf(row+1));
}
return this;
}
private boolean isSelect(int row)
{
int[] sel = reftable.getSelectedRows();
for ( int i=0; i<sel.length; i++ )
{
if (sel[i] == row ) return true;
}
return false;
}
}