最近有个任务,其中需要实现table网格的单元格合并,想了很久,最后用了一种简单但是感觉不怎么好的方式。
大概思路是这样子的:将网格中相同数据的单元格进行合并。所以这里单元格是否要合并取决于单元格的数据是否一样。
以下是详细的实现步骤:
1 、先取消网格的绘制网格线的功能。
JTable table = new JTable();
table.setModel(tableModel);
table.setShowHorizontalLines(false);
table.setShowVerticalLines(false);
2、定义新的网格模型MergeTableModel继承DefaultTableModel,新增一个map用来存放数据值相同的单元格坐标。
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import javax.swing.table.DefaultTableModel;
import com.griddata.MergeTableData;
public class MergeTableModel extends DefaultTableModel {
private static final long serialVersionUID = -5431441008936488938L;
public static final int ROW = 0;
public static final int COLUMN = 1;
// 按照单元格的值分组存放被隐藏掉的单元格坐标
private Map<String, Set<Integer[]>> coverRectIndexMap = new HashMap<String, Set<Integer[]>>();
public final int columnWidth = 200;
public MergeTableModel() {
super();
}
public MergeTableModel(Object[] columnNames, int rowCount) {
super(columnNames, rowCount);
}
public MergeTableModel(MergeTableData[][] data, Object[] columnNames) {
super(data, columnNames);
}
public void addCoverRectIndex(String cellValue, int rowIndex, int colIndex) {
Set<Integer[]> coverSet = this.coverRectIndexMap.get(cellValue);
if (coverSet == null) {
coverSet = new HashSet<Integer[]>();
this.coverRectIndexMap.put(cellValue, coverSet);
coverSet.add(new Integer[] { rowIndex, colIndex });
} else {
if (isCellCovered(coverSet, rowIndex, colIndex)) {
return;
} else {
coverSet.add(new Integer[] { rowIndex, colIndex });
}
}
}
public void removeCoverRectIndex(int rowIndex, int colIndex) {
}
// 判断单元格是否被覆盖
public boolean isCellCovered(String cellValue, int rowIndex, int colIndex) {
Set<Integer[]> coverSet = this.coverRectIndexMap.get(cellValue);
if (coverSet == null) {
return false;
}
return isCellCovered(coverSet, rowIndex, colIndex);
}
private boolean isCellCovered(Set<Integer[]> coverSet, int rowIndex, int colIndex) {
for (Integer[] intArr : coverSet) {
if (intArr[0] == rowIndex && intArr[1] == colIndex) {
return true;
}
}
return false;
}
/**
* 获取同一组被覆盖的单元格中最大的行号,如果没有覆盖的单元格则返回-1
*
* @param cellValue
* @return
*/
public int getMaxCoverRow(String cellValue) {
Set<Integer[]> coverSet = this.coverRectIndexMap.get(cellValue);
if (coverSet == null) {
return -1;
}
int maxRow = 0;
for (Integer[] intArr : coverSet) {
if (maxRow < intArr[ROW]) {
maxRow = intArr[ROW];
}
}
return maxRow;
}
/**
* 获取同一组被覆盖的单元格中最大的列号,如果没有覆盖的单元格则返回-1
*
* @param cellValue
* @return
*/
public int getMaxCoverColumn(String cellValue) {
Set<Integer[]> coverSet = this.coverRectIndexMap.get(cellValue);
if (coverSet == null) {
return -1;
}
int maxCloumn = 0;
for (Integer[] intArr : coverSet) {
if (maxCloumn < intArr[COLUMN]) {
maxCloumn = intArr[COLUMN];
}
}
return maxCloumn;
}
/**
* 判断当前的值是否有隐藏的单元格
*
* @param cellValue
* @return
*/
public boolean hasCoverColumns(String cellValue) {
Set<Integer[]> coverSet = this.coverRectIndexMap.get(cellValue);
if (coverSet == null || coverSet.size() == 0) {
return false;
}
return true;
}
/**
* 清除所有数据
*/
@SuppressWarnings("rawtypes")
public void removeAllDatas() {
this.setDataVector(new Vector(), new Vector());
fireTableDataChanged();
}
}
MergeCellRender
import java.awt.Component; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.table.DefaultTableCellRenderer; import com.grid.border.PartLineBorder; import com.griddata.MergeTableData; public