当很表格中有很多列的时候出现Scrollbar的时候,当用户拖动Scrollbar那么有的列就会看不见,而用户需
要输入数据的时候,需要对照第一列或前几列以方便输入数据,则需要固定前几列的需求了。像Excle表格
中可以固定前几列,而在JTable中没有直接的方法实现,网上比较流行的方法是用两个JTable,如下图(一)其中
一个talbe渲染固定列的数据,另外一个主table渲染其他数据,然后把渲染固定列数据的表格当做装载主table的
JScrollPane的Row Header。
这样实现就要把表格中的数据拆分成两个TableModel用于其渲染。
其中实现的效果如图二,其详细的代码见 Fixed Demo

图一

图二
很显然这种实现方式有一下缺点:
1)、当用户对于自己的表格有自己实现的自定义的列头,比如行的序列号或增加了选择框等等这样就会有冲突。
2)、如上所说当拆分成两个TableModel的时候,那么要很好的维护两个表格一些属性保持一致将很麻烦,比如
选择,排序等。
3)、最重要的一点就是如果在其原有的项目中增加这一需求,那么这种方法就要修改很多地方,侵入性太强。
基于上述缺点,
Elie Levy 用了另外一种方法,尽管也有些缺点(暂且后面再说),他实现的方法很简单(效果如图三),
就是将要固定的列的内容画在一个另外一个组件上然后将这个组件放在JTable之上,其总是占据其表格的指定需要固定
的列上,这表格的前几列看起来就是固定了的,如图三,我们需要固定前三列,那么我们将前三列的内容画在一个
JLabel上如图中黑色部分,这时候的关键技术就是利用JLayeredPane的原理了,获得JTable的JLayeredPane,然后将这个
画出所要固定列的内容的JLabel加进JLayeredPane,就能忽悠成固定了。

图三
主要实现代码分析,实现主要监听鼠标事件,捕捉所要固定的列的内容予以即时更新,这个类FixTableManager
为了方便我们继承于JTableHeader,那么在这里我们重写paint()方法:以更新拖动Scrollbar的时候列头的现实信息,
代码如:
@Override

public void paint(Graphics g)
{
super.paint(g);
//int division = mouseListener.getDivision();
int division = mouseListener.getDivision();

if (division > 0)
{
Rectangle r = getVisibleRect();
BufferedImage image = new BufferedImage(division, r.height,
BufferedImage.TYPE_INT_ARGB);
Graphics g2 = image.getGraphics();
g2.setClip(0, 0, division, r.height);
g2.setColor(Color.WHITE);
g2.fillRect(0, 0, division, r.height);
super.paint(g2);
g.drawImage(image, r.x, r.y, division, r.height, null);
g2.dispose();
}
}
画完了固定的列的列头,我们就要画表格中的内容了,这里我们就是把这些内容画在一个JLabel上,如下:

private class FixedColumnsDelegate extends JLabel
{

![]()