原创 表头合并单元格. JTable Groupable TableHeader收藏

新一篇: ActionSet/PopupMenu | 旧一篇: O/R Mapping自己开发 Step II

表头合并单元格. 照例不多说了, 看代码吧.

首先需要定义一个接口, 看看表头是怎么合并的

/**
 * 列头组
 * 
 * 
@author Brad.Wu
 * 
@version 1.0
 
*/

public interface Group {
    
/**
     * 获取所在行
     * 
     * 
@return
     
*/

    
public int getRow();

    
/**
     * 获取所在列
     * 
     * 
@return
     
*/

    
public int getColumn();

    
/**
     * 获取占列个数
     * 
     * 
@return
     
*/

    
public int getColumnSpan();

    
/**
     * 获取占行个数
     * 
     * 
@return
     
*/

    
public int getRowSpan();

    
/**
     * 获取文字
     * 
     * 
@return
     
*/

    
public Object getHeaderValue();
}

 这个和HTML的写法其实一样的. 主要就是每个Cell所在的位置, 占的行列数以及文字.

接下来是一个默认的实现. 其实不写接口也可以, 因为通常不会对表头做动作的.

 

/**
 * 默认Group实现
 * 
 * 
@author Brad.Wu
 * 
@version 1.0
 
*/

public class DefaultGroup implements Group {
    
private int row = 0;

    
private int column = 0;

    
private int rowSpan = 1;

    
private int columnSpan = 1;

    
private Object headerValue = null;

    
/*
     * (非 Javadoc)
     * 
     * @see com.eplat.realty.view.component.table.Group#getRow()
     
*/

    
public int getRow() {
        
return this.row;
    }


    
/**
     * 
@param row 要设置的 row。
     
*/

    
public void setRow(int row) {
        
this.row = row;
    }


    
/*
     * (非 Javadoc)
     * 
     * @see com.eplat.realty.view.component.table.Group#getColumn()
     
*/

    
public int getColumn() {
        
return this.column;
    }


    
/**
     * 
@param column 要设置的 column。
     
*/

    
public void setColumn(int column) {
        
this.column = column;
    }


    
/*
     * (非 Javadoc)
     * 
     * @see com.eplat.realty.view.component.table.Group#getColumnSpan()
     
*/

    
public int getColumnSpan() {
        
return this.columnSpan;
    }


    
/**
     * 
@param columnSpan 要设置的 columnSpan。
     
*/

    
public void setColumnSpan(int columnSpan) {
        
this.columnSpan = columnSpan;
    }


    
/*
     * (非 Javadoc)
     * 
     * @see com.eplat.realty.view.component.table.Group#getRowSpan()
     
*/

    
public int getRowSpan() {
        
return this.rowSpan;
    }


    
/**
     * 
@param rowSpan 要设置的 rowSpan。
     
*/

    
public void setRowSpan(int rowSpan) {
        
this.rowSpan = rowSpan;
    }


    
/*
     * (非 Javadoc)
     * 
     * @see com.eplat.realty.view.component.table.Group#getHeaderValue()
     
*/

    
public Object getHeaderValue() {
        
return this.headerValue;
    }


    
/**
     * 
@param headerValue 要设置的 headerValue。
     
*/

    
public void setHeaderValue(Object headerValue) {
        
this.headerValue = headerValue;
    }

}

 

重写一个表头组件

 

import java.awt.Component;
import java.awt.Rectangle;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JTable;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;

/**
 * 可以合并的列头
 * 
 * 
@author Brad.Wu
 * 
@version 1.0
 
*/

@SuppressWarnings(
"serial")
public class GroupableTableHeader extends JTableHeader {
    
private int rowCount = 0;

    
private int columnCount = 0;

    
private List<Group> groups = new ArrayList<Group>();

    
public GroupableTableHeader() {
                                           
// 这个是必须的, 因为如果可以拖动列的位置, 那么一切都完蛋了.
                                           
// 如果你想实现这个功能, 那么只能你自己去做了, 我可不想做这个, 看上去超烦的
        this.setReorderingAllowed(false);
    }


    
/*
     * (非 Javadoc)
     * 
     * @see javax.swing.table.JTableHeader#updateUI()
     
*/

    @Override
    
public void updateUI() {
        setUI(
new GroupableTableHeaderUI());
    }


    
/*
     * 获取指定行列的位置
     
*/

    
public Rectangle getHeaderRect(int row, int column) {
        Rectangle r 
= new Rectangle();
        TableColumnModel cm 
= getColumnModel();

        Group group 
= this.getGroup(row, column);
        r.height 
= getHeight();

        
if (column < 0{
            
// x = width = 0;
            if (!getComponentOrientation().isLeftToRight()) {
                r.x 
= getWidthInRightToLeft();
            }

        }
 else if (column >= cm.getColumnCount()) {
            
if (getComponentOrientation().isLeftToRight()) {
                r.x 
= getWidth();
            }

        }
 else {
            
for (int i = 0; i < group.getColumn(); i++{
                r.x 
+= cm.getColumn(i).getWidth();
            }

            
for (int i = group.getColumn(), j = group.getColumn() + group.getColumnSpan() - 1; i < j; i++{
                r.width 
+= cm.getColumn(i).getWidth();
            }

            
if (!getComponentOrientation().isLeftToRight()) {
                r.x 
= getWidthInRightToLeft() - r.x - r.width;
            }

            
// r.width = cm.getColumn(column).getWidth();
        }

        
return r;
    }


    
/**
     * 获取Group的Y位置
     * 
     * 
@param group
     * 
@return
     
*/

    
public int getYOfGroup(Group group) {
        
int row = group.getRow();
        TableCellRenderer renderer 
= this.getDefaultRenderer();
        Component comp 
= renderer.getTableCellRendererComponent(getTable(), group.getHeaderValue(),
                
falsefalse, group.getRow(), group.getColumn());
        
return row * comp.getPreferredSize().height;
    }


    
/**
     * 获取Group的高度
     * 
     * 
@param group
     * 
@return
     
*/

    
public int getHeightOfGroup(Group group) {
        
int rowSpan = group.getRowSpan();
        TableCellRenderer renderer 
= this.getDefaultRenderer();
        Component comp 
= renderer.getTableCellRendererComponent(getTable(), group.getHeaderValue(),
                
falsefalse, group.getRow(), group.getColumn());
        
return rowSpan * comp.getPreferredSize().height;
    }


    
private int getWidthInRightToLeft() {
        
if ((table != null&& (table.getAutoResizeMode() != JTable.AUTO_RESIZE_OFF)) {
            
return table.getWidth();
        }

        
return super.getWidth();
    }


    
/**
     * 增加Group
     * 
     * 
@param group
     
*/

    
public void addGroup(Group group) {
        groups.add(group);
        
int row = group.getRow();
        
int rowSpan = group.getRowSpan();
        rowCount 
= Math.max(rowCount, row +