最近,我为了做一个管理系统,需要用到合并JTable的单元格。查找了很多资料,终于简单的实现了。现在把代码共享出来,希望对大家有用。
本程序主要实现行的合并,列的合并大家可以根据下面的代码修改。
CMap.java :
package com;
public interface CMap {
/**
* @param row
* logical cell row
* @param column
* logical cell column
* @return number of columns spanned a cell
*/
int span(int row, int column);
/**
* @param row
* logical cell row
* @param column
* logical cell column
* @return the index of a visible cell covering a logical cell
*/
int visibleCell(int row, int column);
}
CTUI.java :
package com;
import javax.swing.table.*;
import javax.swing.plaf.basic.*;
import java.awt.*;
import javax.swing.*;
public class CTUI extends BasicTableUI {
public void paint(Graphics g, JComponent c) {
Rectangle r = g.getClipBounds();
// int firstRow = table.rowAtPoint(new Point(0, r.y));
// int lastRow = table.rowAtPoint(new Point(0, r.y + r.height));
int firstCol = table.columnAtPoint( new Point( r.x , 0 ) );
int lastCol = table.columnAtPoint(new Point( r.x + r.width, 0 ));
// -1 is a flag that the ending point is outside the table
// if (lastRow < 0)
// lastRow = table.getRowCount() - 1;
if (lastCol < 0)
lastCol = table.getColumnCount() - 1;
for (int i = firstCol; i <= lastCol; i++)
paintCol(i, g);
}
private void paintCol(int col, Graphics g) {
Rectangle r = g.getClipBounds();
for (int i = 0; i < table.getRowCount(); i++) {
Rectangle r1 = table.getCellRect( i, col, true);
if (r1.intersects(r)) // at least a part is visible
{
int sk = ((CTable) table).map.visibleCell( i, col );
paintCell( sk, col, g, r1);
// increment the column counter
i += ((CTable) table).map.span( sk, col ) - 1;
}
}
}
private void paintCell(int row, int column, Graphics g, Rectangle area) {
int verticalMargin = table.getRowMargin();
int horizontalMargin = table.getColumnModel().getColumnMargin();
Color c = g.getColor();
g.setColor(table.getGridColor());
g.drawRect(area.x, area.y, area.width - 1, area.height - 1);
g.setColor(c);
area.setBounds(area.x + horizontalMargin / 2, area.y + verticalMargin
/ 2, area.width - horizontalMargin, area.height
- verticalMargin);
if (table.isEditing() && table.getEditingRow() == row
&& table.getEditingColumn() == column) {
Component component = table.getEditorComponent();
component.setBounds(area);
component.validate();
}
else
{
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component component = table.prepareRenderer(renderer, row, column);
if (component.getParent() == null)
rendererPane.add(component);
rendererPane.paintComponent(g, component, table, area.x, area.y,
area.width, area.height, true);
}
}
}
CTable.java :
package com;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
public class CTable extends JTable {
public CMap map;
public CTable(CMap cmp, TableModel tbl) {
super(tbl);
map = cmp;
setUI(new CTUI());
}
public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
// required because getCellRect is used in JTable constructor
if (map == null)
return super.getCellRect(row, column, includeSpacing);
// add widths of all spanned logical cells
int sk = map.visibleCell(row, column);
//Rectangle r1 = super.getCellRect(row, sk, includeSpacing);
Rectangle r1 = super.getCellRect( sk, column, includeSpacing);
if (map.span( sk, column ) != 1)
for (int i = 1; i < map.span( sk, column ); i++) {
//r1.width += getColumnModel().getColumn(sk + i).getWidth();
r1.height += this.getRowHeight( sk + i );
}
return r1;
}
public int rowAtPoint(Point p) {
int x = super.columnAtPoint(p);
// -1 is returned by columnAtPoint if the point is not in the table
if (x < 0)
return x;
int y = super.rowAtPoint(p);
return map.visibleCell(y, x);
}
}
CMap1.java :
/******************************************************************************************
CMap1对CMap地实现
span( ) 表示合并的单元格的列,返回的是合并的格数。
visibleCell() 表示要渲染的格。返回的渲染的开始格的行。
本程序的table是16行10列,合并的单元格是第一列和最后一列(最后一列是第10列)每两个行。
*******************************************************************************************/
package com;
import javax.swing.*;
import javax.swing.table.*;
class CMap1 implements CMap {
public int span(int row, int column) {
if( column == 0 || column == 9 )
return 2;
return 1;
}
public int visibleCell(int row, int column) {
if( ( ( row >= 0 ) && ( row < 2 ) ) && ( column == 0 || column == 9 ) )
return 0;
if( ( ( row >= 2 ) && ( row < 4 ) ) && ( column == 0 || column == 9 ) )
return 2;
if( ( ( row >= 4 ) && ( row < 6 ) ) && ( column == 0 || column == 9 ) )
return 4;
if( ( ( row >= 6 ) && ( row < 8 ) ) && ( column == 0 || column == 9 ) )
return 6;
if( ( ( row >= 8 ) && ( row < 10 ) ) && ( column == 0 || column == 9 ) )
return 8;
if( ( ( row >= 10 ) && ( row < 12 ) ) && ( column == 0 || column == 9 ) )
return 10;
if( ( ( row >= 12 ) && ( row < 14 ) ) && ( column == 0 || column == 9 ) )
return 12;
if( ( ( row >= 14 ) && ( row < 16 ) ) && ( column == 0 || column == 9 ) )
return 14;
System.out.println( ">>>row = " + row + "column = " + column );
return row;
}
}
下面的程序进行测试。
package com;
import javax.swing.*;
import javax.swing.table.*;
public class CTest {
public static void main(String args[]) {
JFrame jf = new JFrame("Table with cell spanning");
CMap m = new CMap1();
DefaultTableModel tm = new DefaultTableModel( 16, 10 ){
public boolean isCellEditable( int indexRow, int indexColumn )
{
return false;
}
};
//tm.isCellEditable( 16, 10 );
tm.setValueAt( "port1", 0, 0);//对一个合并的单元格填一个数据。
jf.getContentPane().add(new JScrollPane(new CTable(m, tm)));
jf.setDefaultCloseOperation(jf.EXIT_ON_CLOSE);
jf.setSize(500, 500);
jf.show();
}
}