我是靠谱客的博主 隐形冬天,最近开发中收集的这篇文章主要介绍Java Swing写的支持合并单元格的JTable,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

年前在网上参加了一个JavaSwing的招聘上机考试。招聘方要求开发一个类似EXCEL支持单元格合并的JTable。差不多用了5天的时间提交代码,最后被告知测试通过,我提出是否可做兼职,对方回复需要到上海做全职开发,最后也就放弃了。最近公司的一个项目中需要用到以前的代码,偶又重构了一次,设计思想来源于ListSelectionModel。

 



GridBagModel:抽象模型接口。该接口用于描述表格中单元格的合并状态。
DefaultGridBagTableModel:GridBagModel的默认实现。
GridBagTable:继承自JTable的控制器。通过该类中的方法控制表格单元的合并和拆分。
GridBagTableUI:GridBagTable对应的UI。

TODO:(已合并)行、列的插入,删除操作对应的GridBagModel的修改,不过已留接口。

Java代码 复制代码  收藏代码
  1. package org.dxj.guitools.gridbagtable;   
  2. import java.awt.Component;   
  3. import java.awt.Point;   
  4. import java.awt.Rectangle;   
  5. import java.util.Enumeration;   
  6. import java.util.EventObject;   
  7.   
  8. import javax.swing.DefaultCellEditor;   
  9. import javax.swing.JTable;   
  10. import javax.swing.SwingUtilities;   
  11. import javax.swing.event.TableModelEvent;   
  12. import javax.swing.table.AbstractTableModel;   
  13. import javax.swing.table.TableColumn;   
  14. import javax.swing.table.TableColumnModel;   
  15.   
  16. /**  
  17.  * @author 15860102@qq.com  
  18.  */  
  19. public class GridBagTable extends JTable{   
  20.   
  21.     GridBagModel gridBagModel;   
  22.        
  23.     public GridBagModel getGridBagModel() {   
  24.         return gridBagModel;   
  25.     }   
  26.        
  27.     public void setGridBagModel(GridBagModel gridBagModel){   
  28.         if( gridBagModel != null && gridBagModel != this.gridBagModel )   
  29.             this.gridBagModel = gridBagModel;   
  30.     }   
  31.   
  32.     public GridBagTable(AbstractTableModel dm){   
  33.         super(dm);         
  34.         getTableHeader().setReorderingAllowed(false);   
  35.         gridBagModel = new DefaultGridBagTableModel(dm);           
  36.         getColumnModel().setColumnSelectionAllowed(true);   
  37.     }   
  38.        
  39.      private void updateSubComponentUI(Object componentShell) {   
  40.         if (componentShell == null) {   
  41.             return;   
  42.         }   
  43.         Component component = null;   
  44.         if (componentShell instanceof Component) {   
  45.             component = (Component)componentShell;   
  46.         }   
  47.         if (componentShell instanceof DefaultCellEditor) {   
  48.             component = ((DefaultCellEditor)componentShell).getComponent();   
  49.         }   
  50.   
  51.         if (component != null) {   
  52.             SwingUtilities.updateComponentTreeUI(component);   
  53.         }   
  54.     }   
  55.        
  56.     public void updateUI() {       
  57.         // Update the UIs of the cell renderers, cell editors and header renderers.   
  58.         TableColumnModel cm = getColumnModel();   
  59.         for(int column = 0; column < cm.getColumnCount(); column++) {   
  60.             TableColumn aColumn = cm.getColumn(column);   
  61.         updateSubComponentUI(aColumn.getCellRenderer());   
  62.             updateSubComponentUI(aColumn.getCellEditor());   
  63.         updateSubComponentUI(aColumn.getHeaderRenderer());   
  64.         }   
  65.   
  66.         // Update the UIs of all the default renderers.   
  67.         Enumeration defaultRenderers = defaultRenderersByColumnClass.elements();   
  68.         while (defaultRenderers.hasMoreElements()) {   
  69.             updateSubComponentUI(defaultRenderers.nextElement());   
  70.         }   
  71.   
  72.         // Update the UIs of all the default editors.   
  73.         Enumeration defaultEditors = defaultEditorsByColumnClass.elements();   
  74.         while (defaultEditors.hasMoreElements()) {   
  75.             updateSubComponentUI(defaultEditors.nextElement());   
  76.         }   
  77.   
  78.         // Update the UI of the table header   
  79.         if (tableHeader != null && tableHeader.getParent() == null) {   
  80.             tableHeader.updateUI();   
  81.         }   
  82.         setUI(new GridBagTableUI());   
  83.     }   
  84.        
  85.     public Rectangle getGridCellRect(int row, int column, boolean includeSpacing){   
  86.         return super.getCellRect(row, column, includeSpacing);   
  87.     }   
  88.        
  89.     public Rectangle getCellRect(int row, int column, boolean includeSpacing) {        
  90.         Rectangle cellRect = super.getCellRect(row, column, includeSpacing);   
  91.         int cols = gridBagModel.getColumnGrid(row, column);   
  92.         TableColumnModel cm = getColumnModel();   
  93.         forint n=1; n<cols; n++)   
  94.             cellRect.width += cm.getColumn(column+n).getWidth();   
  95.         int rows = gridBagModel.getRowGrid(row, column);   
  96.         forint n=1; n<rows; n++)   
  97.             cellRect.height += getRowHeight(row+n);   
  98.         return cellRect;            
  99.     }   
  100.        
  101.     public void tableChanged(TableModelEvent e){   
  102.         super.tableChanged(e);   
  103.         //TODO   
  104.     }   
  105.        
  106.     public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn){   
  107.         if( gridBagModel.mergeCells(startRow, endRow, startColumn, endColumn)){   
  108.             repaint();   
  109.             return true;   
  110.         }      
  111.         return false;   
  112.     }   
  113.         
  114.     public boolean mergeCells(int[] rows, int[] columns){   
  115.         if( gridBagModel.mergeCells(rows, columns)){   
  116.             repaint();   
  117.             return true;   
  118.         }      
  119.         return false;   
  120.     }   
  121.        
  122.     public boolean spliteCellAt(int row, int column){   
  123.         if( gridBagModel.spliteCellAt(row, column)){   
  124.             repaint();   
  125.             return true;   
  126.         }   
  127.         return false;   
  128.     }   
  129.        
  130.     public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {   
  131.         if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED  )   
  132.             super.changeSelection(rowIndex, columnIndex, toggle, extend);   
  133.         Point p;   
  134.         forint row = rowIndex; row >= 0; row-- ){   
  135.             forint col = columnIndex; col >= 0; col-- ){   
  136.                 p = gridBagModel.getGrid(row, col);   
  137.                 //p = ((Point)((Vector)rowVector.get(row)).get(col));   
  138.                 if( col + p.x > columnIndex && row + p.y > rowIndex){   
  139.                     rowIndex = row;   
  140.                     columnIndex = col;   
  141.                     break;   
  142.                 }   
  143.             }   
  144.         }      
  145.         super.changeSelection(rowIndex, columnIndex, toggle, extend);   
  146.         repaint();   
  147.     }   
  148.        
  149.     public boolean editCellAt(int rowIndex, int columnIndex, EventObject e){   
  150.         if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED  )   
  151.             return super.editCellAt(rowIndex, columnIndex, e);      
  152.         Point p;   
  153.         forint row = rowIndex; row >= 0; row-- ){   
  154.             forint col = columnIndex; col >= 0; col-- ){   
  155.                 p = gridBagModel.getGrid(row, col);   
  156.                 if( col + p.x > columnIndex && row + p.y > rowIndex){   
  157.                     rowIndex = row;   
  158.                     columnIndex = col;   
  159.                     break;   
  160.                 }   
  161.             }   
  162.         }          
  163.         return super.editCellAt(rowIndex, columnIndex, e);           
  164.     }   
  165. }  
package org.dxj.guitools.gridbagtable;
import java.awt.Component;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Enumeration;
import java.util.EventObject;
import javax.swing.DefaultCellEditor;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.event.TableModelEvent;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
/**
* @author 15860102@qq.com
*/
public class GridBagTable extends JTable{
GridBagModel gridBagModel;
public GridBagModel getGridBagModel() {
return gridBagModel;
}
public void setGridBagModel(GridBagModel gridBagModel){
if( gridBagModel != null && gridBagModel != this.gridBagModel )
this.gridBagModel = gridBagModel;
}
public GridBagTable(AbstractTableModel dm){
super(dm);
getTableHeader().setReorderingAllowed(false);
gridBagModel = new DefaultGridBagTableModel(dm);
getColumnModel().setColumnSelectionAllowed(true);
}
private void updateSubComponentUI(Object componentShell) {
if (componentShell == null) {
return;
}
Component component = null;
if (componentShell instanceof Component) {
component = (Component)componentShell;
}
if (componentShell instanceof DefaultCellEditor) {
component = ((DefaultCellEditor)componentShell).getComponent();
}
if (component != null) {
SwingUtilities.updateComponentTreeUI(component);
}
}
public void updateUI() {
// Update the UIs of the cell renderers, cell editors and header renderers.
TableColumnModel cm = getColumnModel();
for(int column = 0; column < cm.getColumnCount(); column++) {
TableColumn aColumn = cm.getColumn(column);
updateSubComponentUI(aColumn.getCellRenderer());
updateSubComponentUI(aColumn.getCellEditor());
updateSubComponentUI(aColumn.getHeaderRenderer());
}
// Update the UIs of all the default renderers.
Enumeration defaultRenderers = defaultRenderersByColumnClass.elements();
while (defaultRenderers.hasMoreElements()) {
updateSubComponentUI(defaultRenderers.nextElement());
}
// Update the UIs of all the default editors.
Enumeration defaultEditors = defaultEditorsByColumnClass.elements();
while (defaultEditors.hasMoreElements()) {
updateSubComponentUI(defaultEditors.nextElement());
}
// Update the UI of the table header
if (tableHeader != null && tableHeader.getParent() == null) {
tableHeader.updateUI();
}
setUI(new GridBagTableUI());
}
public Rectangle getGridCellRect(int row, int column, boolean includeSpacing){
return super.getCellRect(row, column, includeSpacing);
}
public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
Rectangle cellRect = super.getCellRect(row, column, includeSpacing);
int cols = gridBagModel.getColumnGrid(row, column);
TableColumnModel cm = getColumnModel();
for( int n=1; n<cols; n++)
cellRect.width += cm.getColumn(column+n).getWidth();
int rows = gridBagModel.getRowGrid(row, column);
for( int n=1; n<rows; n++)
cellRect.height += getRowHeight(row+n);
return cellRect;
}
public void tableChanged(TableModelEvent e){
super.tableChanged(e);
//TODO
}
public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn){
if( gridBagModel.mergeCells(startRow, endRow, startColumn, endColumn)){
repaint();
return true;
}
return false;
}
public boolean mergeCells(int[] rows, int[] columns){
if( gridBagModel.mergeCells(rows, columns)){
repaint();
return true;
}
return false;
}
public boolean spliteCellAt(int row, int column){
if( gridBagModel.spliteCellAt(row, column)){
repaint();
return true;
}
return false;
}
public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED
)
super.changeSelection(rowIndex, columnIndex, toggle, extend);
Point p;
for( int row = rowIndex; row >= 0; row-- ){
for( int col = columnIndex; col >= 0; col-- ){
p = gridBagModel.getGrid(row, col);
//p = ((Point)((Vector)rowVector.get(row)).get(col));
if( col + p.x > columnIndex && row + p.y > rowIndex){
rowIndex = row;
columnIndex = col;
break;
}
}
}
super.changeSelection(rowIndex, columnIndex, toggle, extend);
repaint();
}
public boolean editCellAt(int rowIndex, int columnIndex, EventObject e){
if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED
)
return super.editCellAt(rowIndex, columnIndex, e);
Point p;
for( int row = rowIndex; row >= 0; row-- ){
for( int col = columnIndex; col >= 0; col-- ){
p = gridBagModel.getGrid(row, col);
if( col + p.x > columnIndex && row + p.y > rowIndex){
rowIndex = row;
columnIndex = col;
break;
}
}
}
return super.editCellAt(rowIndex, columnIndex, e);
}
}
 
Java代码 复制代码  收藏代码
  1. package org.dxj.guitools.gridbagtable;   
  2.   
  3. import java.awt.Point;   
  4.   
  5. public interface GridBagModel {   
  6.     //格子处于正常状态   
  7.     int DEFAULT = 0;   
  8.     //格子合并了其他的格子   
  9.     int MERGE = 1;   
  10.     //格子被其他格子合并   
  11.     int COVERED = -1;   
  12.        
  13.     /**  
  14.      * @param row 行  
  15.      * @param column 列  
  16.      * @return 该单元格在行、列的跨度  
  17.      */  
  18.     Point getGrid(int row, int column);   
  19.        
  20.     /**  
  21.      * 在Y轴方向的跨度  
  22.      * @param row  
  23.      * @param column  
  24.      * @return  
  25.      */  
  26.     int getRowGrid(int row, int column);   
  27.        
  28.     /**  
  29.      * 在X轴方向的跨度  
  30.      * @param row  
  31.      * @param column  
  32.      * @return  
  33.      */  
  34.     int getColumnGrid(int row, int column);   
  35.   
  36.     /**  
  37.      * @param rows 行集合  
  38.      * @param columns 列集合  
  39.      * @return 单元格集合是否可以合并在一起  
  40.      */  
  41.     boolean canMergeCells(int[] rows, int[] columns);   
  42.        
  43.     /**  
  44.      * 判断该单元格状态  
  45.      * @param row  
  46.      * @param column  
  47.      * @return MERGE|DEFAULT|COVERED  
  48.      */  
  49.     int getCellState(int row, int column);   
  50.        
  51.     /**  
  52.      * 将单元格集合合并  
  53.      * @param startRow 开始行  
  54.      * @param endRow 结束行  
  55.      * @param startColumn 开始列  
  56.      * @param endColumn 结束列  
  57.      * @return 是否合并成功  
  58.      */  
  59.     boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn);   
  60.        
  61.     /**  
  62.      * 将单元格集合合并  
  63.      * @param rows 行集合  
  64.      * @param columns 列集合  
  65.      * @return 是否合并成功  
  66.      */  
  67.     boolean mergeCells(int[] rows, int[] columns);   
  68.        
  69.     /**  
  70.      * 拆分单元格  
  71.      * @param row 行  
  72.      * @param column 列  
  73.      * @return 是否拆分成功  
  74.      */  
  75.     boolean spliteCellAt(int row, int column);   
  76.        
  77.     /**  
  78.      * 清除 所有合并  
  79.      */  
  80.     void clearMergence();   
  81. }  
package org.dxj.guitools.gridbagtable;
import java.awt.Point;
public interface GridBagModel {
//格子处于正常状态
int DEFAULT = 0;
//格子合并了其他的格子
int MERGE = 1;
//格子被其他格子合并
int COVERED = -1;
/**
* @param row 行
* @param column 列
* @return 该单元格在行、列的跨度
*/
Point getGrid(int row, int column);
/**
* 在Y轴方向的跨度
* @param row
* @param column
* @return
*/
int getRowGrid(int row, int column);
/**
* 在X轴方向的跨度
* @param row
* @param column
* @return
*/
int getColumnGrid(int row, int column);
/**
* @param rows 行集合
* @param columns 列集合
* @return 单元格集合是否可以合并在一起
*/
boolean canMergeCells(int[] rows, int[] columns);
/**
* 判断该单元格状态
* @param row
* @param column
* @return MERGE|DEFAULT|COVERED
*/
int getCellState(int row, int column);
/**
* 将单元格集合合并
* @param startRow 开始行
* @param endRow 结束行
* @param startColumn 开始列
* @param endColumn 结束列
* @return 是否合并成功
*/
boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn);
/**
* 将单元格集合合并
* @param rows 行集合
* @param columns 列集合
* @return 是否合并成功
*/
boolean mergeCells(int[] rows, int[] columns);
/**
* 拆分单元格
* @param row 行
* @param column 列
* @return 是否拆分成功
*/
boolean spliteCellAt(int row, int column);
/**
* 清除 所有合并
*/
void clearMergence();
}
 
Java代码 复制代码  收藏代码
  1. package org.dxj.guitools.gridbagtable;   
  2.   
  3. import java.awt.Point;   
  4. import java.util.Arrays;   
  5. import java.util.List;   
  6. import java.util.Vector;   
  7.   
  8. import javax.swing.event.TableModelEvent;   
  9. import javax.swing.event.TableModelListener;   
  10. import javax.swing.table.AbstractTableModel;   
  11.   
  12. public class DefaultGridBagTableModel implements GridBagModel, TableModelListener{   
  13.     protected AbstractTableModel model;   
  14.     protected List<List<Point>> gridInfo;   
  15.        
  16.     DefaultGridBagTableModel(AbstractTableModel model){   
  17.         gridInfo = new Vector<List<Point>>();   
  18.         setTableModel(model);   
  19.     }   
  20.        
  21.     public void setTableModel(AbstractTableModel model){   
  22.         if( model != null && model != this.model ){   
  23.             ifthis.model != null )   
  24.                 this.model.removeTableModelListener(this);   
  25.             //防止多次添加监听器   
  26.             model.removeTableModelListener(this);   
  27.             model.addTableModelListener(this);   
  28.             this.model = model;   
  29.             clearMergence();   
  30.         }   
  31.     }   
  32.        
  33.     public void clearMergence(){   
  34.         if( gridInfo == null  )   
  35.             gridInfo = new Vector<List<Point>>();   
  36.         else  
  37.             gridInfo.clear();   
  38.            
  39.         if( model == null )   
  40.             return;   
  41.            
  42.         //初始化,每个格子占的格子数为(1,1);   
  43.         for(int row=model.getRowCount(); --row>=0;){   
  44.             List<Point> infos = new Vector<Point>();   
  45.             gridInfo.add(infos);   
  46.             for(int col=model.getColumnCount(); --col>=0;){   
  47.                 infos.add(getDefaultPoint());   
  48.             }   
  49.         }   
  50.     }   
  51.        
  52.     public Point getDefaultPoint(){   
  53.         return new Point(1,1);   
  54.     }   
  55.        
  56.     @Override  
  57.     public boolean canMergeCells(int[] rows, int[] columns) {   
  58.         if( rows == null || columns == null ) return false;   
  59.         Arrays.sort(rows);   
  60.         for(int index=0; index<rows.length-1; index++){   
  61.             if( rows[index+1] - rows[index] > 1 )   
  62.                 return false;   
  63.         }   
  64.         Arrays.sort(columns);   
  65.         for(int index=0; index<columns.length-1; index++){   
  66.             if( columns[index+1] - columns[index] > 1 )   
  67.                 return false;   
  68.         }   
  69.         return true;   
  70.     }   
  71.        
  72.     @Override  
  73.     public int getCellState(int row, int column) {   
  74.         Point grid = getGrid(row, column);   
  75.         if( grid == null ) return DEFAULT;   
  76.         if( grid.x>1 || grid.y>1 )   
  77.             return MERGE;   
  78.         if( grid.x<=0 || grid.y<=0 )   
  79.             return COVERED;   
  80.         return DEFAULT;   
  81.     }   
  82.   
  83.     @Override  
  84.     public int getColumnGrid(int row, int column) {   
  85.         if( gridInfo != null && row >=0 && row < gridInfo.size() ){   
  86.             List<Point> gridRow = gridInfo.get(row);   
  87.             if( gridRow != null && column >=0 && column < gridRow.size() ){   
  88.                 Point point = gridRow.get(column);   
  89.                 if( point != null )   
  90.                     return point.x;   
  91.             }      
  92.         }   
  93.         return 1;   
  94.     }   
  95.   
  96.     @Override  
  97.     public Point getGrid(int row, int column) {   
  98.         if( gridInfo != null && row >=0 && row < gridInfo.size() ){   
  99.             List<Point> gridRow = gridInfo.get(row);   
  100.             if( gridRow != null && column >=0 && column < gridRow.size() ){   
  101.                 return gridRow.get(column);   
  102.             }      
  103.         }   
  104.         return getDefaultPoint();   
  105.     }   
  106.   
  107.     @Override  
  108.     public int getRowGrid(int row, int column) {   
  109.         if( gridInfo != null && row >=0 && row < gridInfo.size() ){   
  110.             List<Point> gridRow = gridInfo.get(row);   
  111.             if( gridRow != null && column >=0 && column < gridRow.size() ){   
  112.                 Point point = gridRow.get(column);   
  113.                 if( point != null )   
  114.                     return point.y;   
  115.             }      
  116.         }   
  117.         return 1;   
  118.     }   
  119.   
  120.     protected boolean setGrid(int row, int column, Point grid) {   
  121.         if( gridInfo != null && row >=0 && row < gridInfo.size() ){   
  122.             List<Point> gridRow = gridInfo.get(row);   
  123.             if( gridRow != null && column >=0 && column < gridRow.size() ){   
  124.                 Point point = gridRow.get(column);   
  125.                 if( point != null ){   
  126.                     point.setLocation(grid);   
  127.                 }   
  128.                 else{   
  129.                     gridRow.set(column, grid.getLocation());   
  130.                 }   
  131.                 return true;   
  132.             }      
  133.         }   
  134.         return false;   
  135.     }   
  136.   
  137.     @Override  
  138.     public boolean spliteCellAt(int row, int column) {   
  139.         if( gridInfo != null && row >=0 && row < gridInfo.size() ){   
  140.             List<Point> gridRow = gridInfo.get(row);   
  141.             if( gridRow != null && column >=0 && column < gridRow.size() ){   
  142.                 Point point = gridRow.get(column);   
  143.                 if( point != null ){   
  144.                     point = point.getLocation();   
  145.                     for(int a=0; a<point.y; a++){   
  146.                         for(int b=0; b<point.x; b++){   
  147.                             setGrid(row+a, column+b, getDefaultPoint());   
  148.                         }   
  149.                     }   
  150.                 }   
  151.                 else{   
  152.                     gridRow.set(column, getDefaultPoint());   
  153.                 }   
  154.                 return true;   
  155.             }      
  156.         }   
  157.         return false;   
  158.     }   
  159.        
  160.     @Override  
  161.     /**  
  162.      * table中发生行的添加和删除的时候需要修改该模型  
  163.      */  
  164.     public void tableChanged(TableModelEvent e) {   
  165.         //TODO   
  166.     }   
  167.        
  168.     @Override  
  169.     public boolean mergeCells(int[] rows, int[] columns) {   
  170.         if( !canMergeCells(rows, columns) )   
  171.             return false;   
  172.         Arrays.sort(rows);   
  173.         Arrays.sort(columns);   
  174.         return mergeCells(rows[0],rows[rows.length-1],columns[0],columns[columns.length-1]);   
  175.     }   
  176.   
  177.     @Override  
  178.     public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn) {   
  179.         setGrid(startRow, startColumn, new Point(endColumn-startColumn+1, endRow-startRow+1));    
  180.         for(int row=startRow; row<=endRow; row++){   
  181.             for(int col=startColumn; col<=endColumn; col++){   
  182.                 if(row==startRow&&col==startColumn)   
  183.                     continue;   
  184.                 else  
  185.                     setGrid(row, col, new Point(COVERED,COVERED));    
  186.             }   
  187.         }   
  188.         return true;   
  189.     }   
  190.        
  191.     public String toString(){   
  192.         if( gridInfo == null )   
  193.             return "";   
  194.         StringBuffer sb = new StringBuffer();   
  195.         for(List<Point> rowInfo : gridInfo ){   
  196.             for(Point grid : rowInfo){   
  197.                 sb.append("["+grid.x+","+grid.y+"], ");   
  198.             }   
  199.             sb.append("n");   
  200.         }   
  201.         return sb.toString();   
  202.     }   
  203. }  
package org.dxj.guitools.gridbagtable;
import java.awt.Point;
import java.util.Arrays;
import java.util.List;
import java.util.Vector;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
public class DefaultGridBagTableModel implements GridBagModel, TableModelListener{
protected AbstractTableModel model;
protected List<List<Point>> gridInfo;
DefaultGridBagTableModel(AbstractTableModel model){
gridInfo = new Vector<List<Point>>();
setTableModel(model);
}
public void setTableModel(AbstractTableModel model){
if( model != null && model != this.model ){
if( this.model != null )
this.model.removeTableModelListener(this);
//防止多次添加监听器
model.removeTableModelListener(this);
model.addTableModelListener(this);
this.model = model;
clearMergence();
}
}
public void clearMergence(){
if( gridInfo == null
)
gridInfo = new Vector<List<Point>>();
else
gridInfo.clear();
if( model == null )
return;
//初始化,每个格子占的格子数为(1,1);
for(int row=model.getRowCount(); --row>=0;){
List<Point> infos = new Vector<Point>();
gridInfo.add(infos);
for(int col=model.getColumnCount(); --col>=0;){
infos.add(getDefaultPoint());
}
}
}
public Point getDefaultPoint(){
return new Point(1,1);
}
@Override
public boolean canMergeCells(int[] rows, int[] columns) {
if( rows == null || columns == null ) return false;
Arrays.sort(rows);
for(int index=0; index<rows.length-1; index++){
if( rows[index+1] - rows[index] > 1 )
return false;
}
Arrays.sort(columns);
for(int index=0; index<columns.length-1; index++){
if( columns[index+1] - columns[index] > 1 )
return false;
}
return true;
}
@Override
public int getCellState(int row, int column) {
Point grid = getGrid(row, column);
if( grid == null ) return DEFAULT;
if( grid.x>1 || grid.y>1 )
return MERGE;
if( grid.x<=0 || grid.y<=0 )
return COVERED;
return DEFAULT;
}
@Override
public int getColumnGrid(int row, int column) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
Point point = gridRow.get(column);
if( point != null )
return point.x;
}
}
return 1;
}
@Override
public Point getGrid(int row, int column) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
return gridRow.get(column);
}
}
return getDefaultPoint();
}
@Override
public int getRowGrid(int row, int column) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
Point point = gridRow.get(column);
if( point != null )
return point.y;
}
}
return 1;
}
protected boolean setGrid(int row, int column, Point grid) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
Point point = gridRow.get(column);
if( point != null ){
point.setLocation(grid);
}
else{
gridRow.set(column, grid.getLocation());
}
return true;
}
}
return false;
}
@Override
public boolean spliteCellAt(int row, int column) {
if( gridInfo != null && row >=0 && row < gridInfo.size() ){
List<Point> gridRow = gridInfo.get(row);
if( gridRow != null && column >=0 && column < gridRow.size() ){
Point point = gridRow.get(column);
if( point != null ){
point = point.getLocation();
for(int a=0; a<point.y; a++){
for(int b=0; b<point.x; b++){
setGrid(row+a, column+b, getDefaultPoint());
}
}
}
else{
gridRow.set(column, getDefaultPoint());
}
return true;
}
}
return false;
}
@Override
/**
* table中发生行的添加和删除的时候需要修改该模型
*/
public void tableChanged(TableModelEvent e) {
//TODO
}
@Override
public boolean mergeCells(int[] rows, int[] columns) {
if( !canMergeCells(rows, columns) )
return false;
Arrays.sort(rows);
Arrays.sort(columns);
return mergeCells(rows[0],rows[rows.length-1],columns[0],columns[columns.length-1]);
}
@Override
public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn) {
setGrid(startRow, startColumn, new Point(endColumn-startColumn+1, endRow-startRow+1));
for(int row=startRow; row<=endRow; row++){
for(int col=startColumn; col<=endColumn; col++){
if(row==startRow&&col==startColumn)
continue;
else
setGrid(row, col, new Point(COVERED,COVERED));
}
}
return true;
}
public String toString(){
if( gridInfo == null )
return "";
StringBuffer sb = new StringBuffer();
for(List<Point> rowInfo : gridInfo ){
for(Point grid : rowInfo){
sb.append("["+grid.x+","+grid.y+"], ");
}
sb.append("n");
}
return sb.toString();
}
}
 
Java代码 复制代码  收藏代码
  1. package org.dxj.guitools.gridbagtable;   
  2.   
  3. import java.awt.Color;   
  4. import java.awt.Component;   
  5. import java.awt.Dimension;   
  6. import java.awt.Graphics;   
  7. import java.awt.Point;   
  8. import java.awt.Rectangle;   
  9. import java.util.Enumeration;   
  10.   
  11. import javax.swing.BorderFactory;   
  12. import javax.swing.JComponent;   
  13. import javax.swing.JTable;   
  14. import javax.swing.UIManager;   
  15. import javax.swing.plaf.basic.BasicTableUI;   
  16. import javax.swing.table.JTableHeader;   
  17. import javax.swing.table.TableCellRenderer;   
  18. import javax.swing.table.TableColumn;   
  19. import javax.swing.table.TableColumnModel;   
  20.   
  21. public class GridBagTableUI extends BasicTableUI   
  22. {   
  23.     public Dimension getPreferredSize(JComponent c) {   
  24.         long width = 0;   
  25.         Enumeration<TableColumn> enumeration = table.getColumnModel().getColumns();   
  26.         while (enumeration.hasMoreElements()) {   
  27.             TableColumn aColumn = (TableColumn)enumeration.nextElement();   
  28.             width = width + aColumn.getPreferredWidth();   
  29.         }   
  30.         return createTableSize(width);   
  31.     }   
  32.        
  33.     private Dimension createTableSize(long width) {   
  34.         int height = 0;   
  35.         int rowCount = table.getRowCount();   
  36.         if (rowCount > 0 && table.getColumnCount() > 0) {   
  37.             Rectangle r = table.getCellRect(rowCount-10true);   
  38.             height = r.y + r.height;   
  39.         }   
  40.         // Width is always positive. The call to abs() is a workaround for   
  41.         // a bug in the 1.1.6 JIT on Windows.   
  42.         long tmp = Math.abs(width);   
  43.             if (tmp > Integer.MAX_VALUE) {   
  44.                 tmp = Integer.MAX_VALUE;   
  45.             }   
  46.         return new Dimension((int)tmp, height);   
  47.         }   
  48.        
  49.     public void paint(Graphics g, JComponent c) {   
  50.         Rectangle clip = g.getClipBounds();   
  51.   
  52.         Rectangle bounds = table.getBounds();   
  53.         // account for the fact that the graphics has already been translated   
  54.         // into the table's bounds   
  55.         bounds.x = bounds.y = 0;   
  56.   
  57.     if (table.getRowCount() <= 0 || table.getColumnCount() <= 0 ||   
  58.                 // this check prevents us from painting the entire table   
  59.                 // when the clip doesn't intersect our bounds at all   
  60.                 !bounds.intersects(clip)) {   
  61.   
  62.             paintDropLines(g);   
  63.         return;   
  64.     }   
  65.   
  66.         boolean ltr = table.getComponentOrientation().isLeftToRight();   
  67.   
  68.     Point upperLeft = clip.getLocation();   
  69.         if (!ltr) {   
  70.             upperLeft.x++;   
  71.         }   
  72.   
  73.     Point lowerRight = new Point(clip.x + clip.width - (ltr ? 1 : 0),   
  74.                                      clip.y + clip.height);   
  75.   
  76.         int rMin = table.rowAtPoint(upperLeft);   
  77.         int rMax = table.rowAtPoint(lowerRight);   
  78.         // This should never happen (as long as our bounds intersect the clip,   
  79.         // which is why we bail above if that is the case).   
  80.         if (rMin == -1) {   
  81.         rMin = 0;   
  82.         }   
  83.         // If the table does not have enough rows to fill the view we'll get -1.   
  84.         // (We could also get -1 if our bounds don't intersect the clip,   
  85.         // which is why we bail above if that is the case).   
  86.         // Replace this with the index of the last row.   
  87.         if (rMax == -1) {   
  88.         rMax = table.getRowCount()-1;   
  89.         }   
  90.   
  91.         int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);    
  92.         int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);           
  93.         // This should never happen.   
  94.         if (cMin == -1) {   
  95.         cMin = 0;   
  96.         }   
  97.     // If the table does not have enough columns to fill the view we'll get -1.   
  98.         // Replace this with the index of the last column.   
  99.         if (cMax == -1) {   
  100.         cMax = table.getColumnCount()-1;   
  101.         }   
  102.   
  103.         // Paint the grid.   
  104.         //paintGrid(g, rMin, rMax, cMin, cMax);   
  105.   
  106.         // Paint the cells.   
  107.     paintCells(g, rMin, rMax, cMin, cMax);   
  108.   
  109.         paintDropLines(g);   
  110.     }   
  111.        
  112.     private void paintDropLines(Graphics g) {   
  113.         JTable.DropLocation loc = table.getDropLocation();   
  114.         if (loc == null) {   
  115.             return;   
  116.         }   
  117.   
  118.         Color color = UIManager.getColor("Table.dropLineColor");   
  119.         Color shortColor = UIManager.getColor("Table.dropLineShortColor");   
  120.         if (color == null && shortColor == null) {   
  121.             return;   
  122.         }   
  123.   
  124.         Rectangle rect;   
  125.   
  126.         rect = getHDropLineRect(loc);   
  127.         if (rect != null) {   
  128.             int x = rect.x;   
  129.             int w = rect.width;   
  130.             if (color != null) {   
  131.                 extendRect(rect, true);   
  132.                 g.setColor(color);   
  133.                 g.fillRect(rect.x, rect.y, rect.width, rect.height);   
  134.             }   
  135.             if (!loc.isInsertColumn() && shortColor != null) {   
  136.                 g.setColor(shortColor);   
  137.                 g.fillRect(x, rect.y, w, rect.height);   
  138.             }   
  139.         }   
  140.   
  141.         rect = getVDropLineRect(loc);   
  142.         if (rect != null) {   
  143.             int y = rect.y;   
  144.             int h = rect.height;   
  145.             if (color != null) {   
  146.                 extendRect(rect, false);   
  147.                 g.setColor(color);   
  148.                 g.fillRect(rect.x, rect.y, rect.width, rect.height);   
  149.             }   
  150.             if (!loc.isInsertRow() && shortColor != null) {   
  151.                 g.setColor(shortColor);   
  152.                 g.fillRect(rect.x, y, rect.width, h);   
  153.             }   
  154.         }   
  155.     }   
  156.        
  157.     /*  
  158.      * Paints the grid lines within <I>aRect</I>, using the grid  
  159.      * color set with <I>setGridColor</I>. Paints vertical lines  
  160.      * if <code>getShowVerticalLines()</code> returns true and paints  
  161.      * horizontal lines if <code>getShowHorizontalLines()</code>  
  162.      * returns true.  
  163.      */  
  164.     private void paintGrid(Graphics g, int rMin, int rMax, int cMin, int cMax) {   
  165.         g.setColor(table.getGridColor());   
  166.   
  167.         Rectangle minCell = table.getCellRect(rMin, cMin, true);   
  168.         Rectangle maxCell = table.getCellRect(rMax, cMax, true);   
  169.         Rectangle damagedArea = minCell.union( maxCell );   
  170.   
  171.         if (table.getShowHorizontalLines()) {   
  172.             int tableWidth = damagedArea.x + damagedArea.width;   
  173.             int y = damagedArea.y;   
  174.             for (int row = rMin; row <= rMax; row++) {   
  175.                 y += table.getRowHeight(row);   
  176.                 g.drawLine(damagedArea.x, y - 1, tableWidth - 1, y - 1);   
  177.             }   
  178.         }   
  179.         if (table.getShowVerticalLines()) {   
  180.             TableColumnModel cm = table.getColumnModel();   
  181.             int tableHeight = damagedArea.y + damagedArea.height;   
  182.             int x;   
  183.             if (table.getComponentOrientation().isLeftToRight()) {   
  184.                 x = damagedArea.x;   
  185.                 for (int column = cMin; column <= cMax; column++) {   
  186.                     int w = cm.getColumn(column).getWidth();   
  187.                     x += w;   
  188.                     g.drawLine(x - 10, x - 1, tableHeight - 1);   
  189.                 }   
  190.             } else {   
  191.                 x = damagedArea.x;   
  192.                 for (int column = cMax; column >= cMin; column--) {   
  193.                     int w = cm.getColumn(column).getWidth();   
  194.                     x += w;   
  195.                     g.drawLine(x - 10, x - 1, tableHeight - 1);   
  196.                 }   
  197.             }   
  198.         }   
  199.     }   
  200.        
  201.     private void paintCells(Graphics g, int rMin, int rMax, int cMin, int cMax) {   
  202.         JTableHeader header = table.getTableHeader();   
  203.         TableColumn draggedColumn = (header == null) ? null : header.getDraggedColumn();   
  204.   
  205.         TableColumnModel cm = table.getColumnModel();   
  206.         int columnMargin = cm.getColumnMargin();   
  207.             Rectangle cellRect;   
  208.         TableColumn aColumn;   
  209.         int columnWidth;   
  210.         if (table.getComponentOrientation().isLeftToRight()) {   
  211.             for(int row = rMin; row <= rMax; row++) {   
  212.                 if( table instanceof GridBagTable )   
  213.                     cellRect = ((GridBagTable)table).getGridCellRect(row, cMin, false);   
  214.                 else  
  215.                     cellRect = table.getCellRect(row, cMin, false);   
  216.                 for(int column = cMin; column <= cMax; column++) {   
  217.                     aColumn = cm.getColumn(column);   
  218.                     columnWidth = aColumn.getWidth();                                    
  219.                     //TODO   
  220.                     cellRect.width = columnWidth - columnMargin;   
  221.                     int oldHeight = cellRect.height;   
  222.                     if( table instanceof GridBagTable ){   
  223.                         if(((GridBagTable)table).getGridBagModel().getCellState( row, column) == GridBagModel.COVERED ) {   
  224.                             cellRect.width = 0;   
  225.                             cellRect.height = 0;   
  226.                         }   
  227.                         else{   
  228.                             int h = ((GridBagTable)table).getGridBagModel().getColumnGrid(row, column);   
  229.                             if( h >1 ){   
  230.                                 forint n=1; n<h; n++)   
  231.                                     cellRect.width += cm.getColumn(column+n).getWidth();   
  232.                             }   
  233.                             int v = ((GridBagTable)table).getGridBagModel().getRowGrid(row, column);   
  234.                             if( v >1 ){   
  235.                                 forint n=1; n<v; n++)   
  236.                                     cellRect.height += table.getRowHeight(row+n);   
  237.                             }   
  238.                         }              
  239.                     }                                                                          
  240.                     if (aColumn != draggedColumn) {   
  241.                         paintCell(g, cellRect, row, column);   
  242.                     }                          
  243.                     cellRect.height = oldHeight;                       
  244.                     cellRect.x += columnWidth;   
  245.                 }   
  246.             }   
  247.         } else {   
  248.             for(int row = rMin; row <= rMax; row++) {   
  249.                     cellRect = table.getCellRect(row, cMin, false);   
  250.                     aColumn = cm.getColumn(cMin);   
  251.                     if (aColumn != draggedColumn) {   
  252.                         columnWidth = aColumn.getWidth();   
  253.                         cellRect.width = columnWidth - columnMargin;   
  254.                         paintCell(g, cellRect, row, cMin);   
  255.                     }   
  256.                     for(int column = cMin+1; column <= cMax; column++) {   
  257.                         aColumn = cm.getColumn(column);   
  258.                         columnWidth = aColumn.getWidth();   
  259. //                      TODO   
  260.                         cellRect.width = columnWidth - columnMargin;   
  261.                         cellRect.x -= columnWidth;   
  262.                         if (aColumn != draggedColumn) {   
  263.                             paintCell(g, cellRect, row, column);   
  264.                         }   
  265.                 }   
  266.             }   
  267.         }   
  268.   
  269.             // Paint the dragged column if we are dragging.   
  270.             if (draggedColumn != null) {   
  271.             paintDraggedArea(g, rMin, rMax, draggedColumn, header.getDraggedDistance());   
  272.         }   
  273.   
  274.         // Remove any renderers that may be left in the rendererPane.   
  275.         rendererPane.removeAll();   
  276.         }   
  277.        
  278.     private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {   
  279.         if (table.isEditing() && table.getEditingRow()==row &&   
  280.                                  table.getEditingColumn()==column) {   
  281.             Component component = table.getEditorComponent();   
  282.         component.setBounds(cellRect);   
  283.             component.validate();   
  284.         }   
  285.         else {   
  286.             TableCellRenderer renderer = table.getCellRenderer(row, column);   
  287.             Component component = table.prepareRenderer(renderer, row, column);   
  288.                
  289.             if( component instanceof JComponent ){   
  290.                 ((JComponent)component).setBorder(BorderFactory.createLineBorder(Color.gray));   
  291.             }   
  292.             rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,   
  293.                                         cellRect.width, cellRect.height, true);              
  294.         }   
  295.     }   
  296.        
  297.     private Rectangle getHDropLineRect(JTable.DropLocation loc) {   
  298.         if (!loc.isInsertRow()) {   
  299.             return null;   
  300.         }   
  301.   
  302.         int row = loc.getRow();   
  303.         int col = loc.getColumn();   
  304.         if (col >= table.getColumnCount()) {   
  305.             col--;   
  306.         }   
  307.   
  308.         Rectangle rect = table.getCellRect(row, col, true);   
  309.   
  310.         if (row >= table.getRowCount()) {   
  311.             row--;   
  312.             Rectangle prevRect = table.getCellRect(row, col, true);   
  313.             rect.y = prevRect.y + prevRect.height;   
  314.         }   
  315.   
  316.         if (rect.y == 0) {   
  317.             rect.y = -1;   
  318.         } else {   
  319.             rect.y -= 2;   
  320.         }   
  321.   
  322.         rect.height = 3;   
  323.   
  324.         return rect;   
  325.     }   
  326.        
  327.     private void paintDraggedArea(Graphics g, int rMin, int rMax, TableColumn draggedColumn, int distance) {   
  328.         int draggedColumnIndex = viewIndexForColumn(draggedColumn);   
  329.   
  330.         Rectangle minCell = table.getCellRect(rMin, draggedColumnIndex, true);   
  331.     Rectangle maxCell = table.getCellRect(rMax, draggedColumnIndex, true);   
  332.   
  333.     Rectangle vacatedColumnRect = minCell.union(maxCell);   
  334.   
  335.     // Paint a gray well in place of the moving column.   
  336.     g.setColor(table.getParent().getBackground());   
  337.     g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,   
  338.            vacatedColumnRect.width, vacatedColumnRect.height);   
  339.   
  340.     // Move to the where the cell has been dragged.   
  341.     vacatedColumnRect.x += distance;   
  342.   
  343.     // Fill the background.   
  344.     g.setColor(table.getBackground());   
  345.     g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,   
  346.            vacatedColumnRect.width, vacatedColumnRect.height);   
  347.   
  348.     // Paint the vertical grid lines if necessary.   
  349.     if (table.getShowVerticalLines()) {   
  350.         g.setColor(table.getGridColor());   
  351.         int x1 = vacatedColumnRect.x;   
  352.         int y1 = vacatedColumnRect.y;   
  353.         int x2 = x1 + vacatedColumnRect.width - 1;   
  354.         int y2 = y1 + vacatedColumnRect.height - 1;   
  355.         // Left   
  356.         g.drawLine(x1-1, y1, x1-1, y2);   
  357.         // Right   
  358.         g.drawLine(x2, y1, x2, y2);   
  359.     }   
  360.   
  361.     for(int row = rMin; row <= rMax; row++) {   
  362.         // Render the cell value   
  363.         Rectangle r = table.getCellRect(row, draggedColumnIndex, false);   
  364.         r.x += distance;   
  365.         paintCell(g, r, row, draggedColumnIndex);   
  366.   
  367.         // Paint the (lower) horizontal grid line if necessary.   
  368.         if (table.getShowHorizontalLines()) {   
  369.         g.setColor(table.getGridColor());   
  370.         Rectangle rcr = table.getCellRect(row, draggedColumnIndex, true);   
  371.         rcr.x += distance;   
  372.         int x1 = rcr.x;   
  373.         int y1 = rcr.y;   
  374.         int x2 = x1 + rcr.width - 1;   
  375.         int y2 = y1 + rcr.height - 1;   
  376.         g.drawLine(x1, y2, x2, y2);   
  377.         }   
  378.     }   
  379.     }   
  380.        
  381.     private int viewIndexForColumn(TableColumn aColumn) {   
  382.         TableColumnModel cm = table.getColumnModel();   
  383.         for (int column = 0; column < cm.getColumnCount(); column++) {   
  384.             if (cm.getColumn(column) == aColumn) {   
  385.                 return column;   
  386.             }   
  387.         }   
  388.         return -1;   
  389.     }   
  390.        
  391.     private Rectangle extendRect(Rectangle rect, boolean horizontal) {   
  392.         if (rect == null) {   
  393.             return rect;   
  394.         }   
  395.   
  396.         if (horizontal) {   
  397.             rect.x = 0;   
  398.             rect.width = table.getWidth();   
  399.         } else {   
  400.             rect.y = 0;   
  401.   
  402.             if (table.getRowCount() != 0) {   
  403.                 Rectangle lastRect = table.getCellRect(table.getRowCount() - 10true);   
  404.                 rect.height = lastRect.y + lastRect.height;   
  405.             } else {   
  406.                 rect.height = table.getHeight();   
  407.             }   
  408.         }   
  409.   
  410.         return rect;   
  411.     }   
  412.        
  413.     private Rectangle getVDropLineRect(JTable.DropLocation loc) {   
  414.         if (!loc.isInsertColumn()) {   
  415.             return null;   
  416.         }   
  417.   
  418.         boolean ltr = table.getComponentOrientation().isLeftToRight();   
  419.         int col = loc.getColumn();   
  420.         Rectangle rect = table.getCellRect(loc.getRow(), col, true);   
  421.   
  422.         if (col >= table.getColumnCount()) {   
  423.             col--;   
  424.             rect = table.getCellRect(loc.getRow(), col, true);   
  425.             if (ltr) {   
  426.                 rect.x = rect.x + rect.width;   
  427.             }   
  428.         } else if (!ltr) {   
  429.             rect.x = rect.x + rect.width;   
  430.         }   
  431.   
  432.         if (rect.x == 0) {   
  433.             rect.x = -1;   
  434.         } else {   
  435.             rect.x -= 2;   
  436.         }   
  437.            
  438.         rect.width = 3;   
  439.   
  440.         return rect;   
  441.     }   
  442.   
  443. }  // End of Class BasicTableUI  
package org.dxj.guitools.gridbagtable;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.util.Enumeration;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.plaf.basic.BasicTableUI;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
public class GridBagTableUI extends BasicTableUI
{
public Dimension getPreferredSize(JComponent c) {
long width = 0;
Enumeration<TableColumn> enumeration = table.getColumnModel().getColumns();
while (enumeration.hasMoreElements()) {
TableColumn aColumn = (TableColumn)enumeration.nextElement();
width = width + aColumn.getPreferredWidth();
}
return createTableSize(width);
}
private Dimension createTableSize(long width) {
int height = 0;
int rowCount = table.getRowCount();
if (rowCount > 0 && table.getColumnCount() > 0) {
Rectangle r = table.getCellRect(rowCount-1, 0, true);
height = r.y + r.height;
}
// Width is always positive. The call to abs() is a workaround for
// a bug in the 1.1.6 JIT on Windows.
long tmp = Math.abs(width);
if (tmp > Integer.MAX_VALUE) {
tmp = Integer.MAX_VALUE;
}
return new Dimension((int)tmp, height);
}
public void paint(Graphics g, JComponent c) {
Rectangle clip = g.getClipBounds();
Rectangle bounds = table.getBounds();
// account for the fact that the graphics has already been translated
// into the table's bounds
bounds.x = bounds.y = 0;
if (table.getRowCount() <= 0 || table.getColumnCount() <= 0 ||
// this check prevents us from painting the entire table
// when the clip doesn't intersect our bounds at all
!bounds.intersects(clip)) {
paintDropLines(g);
return;
}
boolean ltr = table.getComponentOrientation().isLeftToRight();
Point upperLeft = clip.getLocation();
if (!ltr) {
upperLeft.x++;
}
Point lowerRight = new Point(clip.x + clip.width - (ltr ? 1 : 0),
clip.y + clip.height);
int rMin = table.rowAtPoint(upperLeft);
int rMax = table.rowAtPoint(lowerRight);
// This should never happen (as long as our bounds intersect the clip,
// which is why we bail above if that is the case).
if (rMin == -1) {
rMin = 0;
}
// If the table does not have enough rows to fill the view we'll get -1.
// (We could also get -1 if our bounds don't intersect the clip,
// which is why we bail above if that is the case).
// Replace this with the index of the last row.
if (rMax == -1) {
rMax = table.getRowCount()-1;
}
int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);
int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);
// This should never happen.
if (cMin == -1) {
cMin = 0;
}
// If the table does not have enough columns to fill the view we'll get -1.
// Replace this with the index of the last column.
if (cMax == -1) {
cMax = table.getColumnCount()-1;
}
// Paint the grid.
//paintGrid(g, rMin, rMax, cMin, cMax);
// Paint the cells.
paintCells(g, rMin, rMax, cMin, cMax);
paintDropLines(g);
}
private void paintDropLines(Graphics g) {
JTable.DropLocation loc = table.getDropLocation();
if (loc == null) {
return;
}
Color color = UIManager.getColor("Table.dropLineColor");
Color shortColor = UIManager.getColor("Table.dropLineShortColor");
if (color == null && shortColor == null) {
return;
}
Rectangle rect;
rect = getHDropLineRect(loc);
if (rect != null) {
int x = rect.x;
int w = rect.width;
if (color != null) {
extendRect(rect, true);
g.setColor(color);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
}
if (!loc.isInsertColumn() && shortColor != null) {
g.setColor(shortColor);
g.fillRect(x, rect.y, w, rect.height);
}
}
rect = getVDropLineRect(loc);
if (rect != null) {
int y = rect.y;
int h = rect.height;
if (color != null) {
extendRect(rect, false);
g.setColor(color);
g.fillRect(rect.x, rect.y, rect.width, rect.height);
}
if (!loc.isInsertRow() && shortColor != null) {
g.setColor(shortColor);
g.fillRect(rect.x, y, rect.width, h);
}
}
}
/*
* Paints the grid lines within <I>aRect</I>, using the grid
* color set with <I>setGridColor</I>. Paints vertical lines
* if <code>getShowVerticalLines()</code> returns true and paints
* horizontal lines if <code>getShowHorizontalLines()</code>
* returns true.
*/
private void paintGrid(Graphics g, int rMin, int rMax, int cMin, int cMax) {
g.setColor(table.getGridColor());
Rectangle minCell = table.getCellRect(rMin, cMin, true);
Rectangle maxCell = table.getCellRect(rMax, cMax, true);
Rectangle damagedArea = minCell.union( maxCell );
if (table.getShowHorizontalLines()) {
int tableWidth = damagedArea.x + damagedArea.width;
int y = damagedArea.y;
for (int row = rMin; row <= rMax; row++) {
y += table.getRowHeight(row);
g.drawLine(damagedArea.x, y - 1, tableWidth - 1, y - 1);
}
}
if (table.getShowVerticalLines()) {
TableColumnModel cm = table.getColumnModel();
int tableHeight = damagedArea.y + damagedArea.height;
int x;
if (table.getComponentOrientation().isLeftToRight()) {
x = damagedArea.x;
for (int column = cMin; column <= cMax; column++) {
int w = cm.getColumn(column).getWidth();
x += w;
g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
}
} else {
x = damagedArea.x;
for (int column = cMax; column >= cMin; column--) {
int w = cm.getColumn(column).getWidth();
x += w;
g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
}
}
}
}
private void paintCells(Graphics g, int rMin, int rMax, int cMin, int cMax) {
JTableHeader header = table.getTableHeader();
TableColumn draggedColumn = (header == null) ? null : header.getDraggedColumn();
TableColumnModel cm = table.getColumnModel();
int columnMargin = cm.getColumnMargin();
Rectangle cellRect;
TableColumn aColumn;
int columnWidth;
if (table.getComponentOrientation().isLeftToRight()) {
for(int row = rMin; row <= rMax; row++) {
if( table instanceof GridBagTable )
cellRect = ((GridBagTable)table).getGridCellRect(row, cMin, false);
else
cellRect = table.getCellRect(row, cMin, false);
for(int column = cMin; column <= cMax; column++) {
aColumn = cm.getColumn(column);
columnWidth = aColumn.getWidth();
//TODO
cellRect.width = columnWidth - columnMargin;
int oldHeight = cellRect.height;
if( table instanceof GridBagTable ){
if(((GridBagTable)table).getGridBagModel().getCellState( row, column) == GridBagModel.COVERED ) {
cellRect.width = 0;
cellRect.height = 0;
}
else{
int h = ((GridBagTable)table).getGridBagModel().getColumnGrid(row, column);
if( h >1 ){
for( int n=1; n<h; n++)
cellRect.width += cm.getColumn(column+n).getWidth();
}
int v = ((GridBagTable)table).getGridBagModel().getRowGrid(row, column);
if( v >1 ){
for( int n=1; n<v; n++)
cellRect.height += table.getRowHeight(row+n);
}
}
}
if (aColumn != draggedColumn) {
paintCell(g, cellRect, row, column);
}
cellRect.height = oldHeight;
cellRect.x += columnWidth;
}
}
} else {
for(int row = rMin; row <= rMax; row++) {
cellRect = table.getCellRect(row, cMin, false);
aColumn = cm.getColumn(cMin);
if (aColumn != draggedColumn) {
columnWidth = aColumn.getWidth();
cellRect.width = columnWidth - columnMargin;
paintCell(g, cellRect, row, cMin);
}
for(int column = cMin+1; column <= cMax; column++) {
aColumn = cm.getColumn(column);
columnWidth = aColumn.getWidth();
//
TODO
cellRect.width = columnWidth - columnMargin;
cellRect.x -= columnWidth;
if (aColumn != draggedColumn) {
paintCell(g, cellRect, row, column);
}
}
}
}
// Paint the dragged column if we are dragging.
if (draggedColumn != null) {
paintDraggedArea(g, rMin, rMax, draggedColumn, header.getDraggedDistance());
}
// Remove any renderers that may be left in the rendererPane.
rendererPane.removeAll();
}
private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
if (table.isEditing() && table.getEditingRow()==row &&
table.getEditingColumn()==column) {
Component component = table.getEditorComponent();
component.setBounds(cellRect);
component.validate();
}
else {
TableCellRenderer renderer = table.getCellRenderer(row, column);
Component component = table.prepareRenderer(renderer, row, column);
if( component instanceof JComponent ){
((JComponent)component).setBorder(BorderFactory.createLineBorder(Color.gray));
}
rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
cellRect.width, cellRect.height, true);
}
}
private Rectangle getHDropLineRect(JTable.DropLocation loc) {
if (!loc.isInsertRow()) {
return null;
}
int row = loc.getRow();
int col = loc.getColumn();
if (col >= table.getColumnCount()) {
col--;
}
Rectangle rect = table.getCellRect(row, col, true);
if (row >= table.getRowCount()) {
row--;
Rectangle prevRect = table.getCellRect(row, col, true);
rect.y = prevRect.y + prevRect.height;
}
if (rect.y == 0) {
rect.y = -1;
} else {
rect.y -= 2;
}
rect.height = 3;
return rect;
}
private void paintDraggedArea(Graphics g, int rMin, int rMax, TableColumn draggedColumn, int distance) {
int draggedColumnIndex = viewIndexForColumn(draggedColumn);
Rectangle minCell = table.getCellRect(rMin, draggedColumnIndex, true);
Rectangle maxCell = table.getCellRect(rMax, draggedColumnIndex, true);
Rectangle vacatedColumnRect = minCell.union(maxCell);
// Paint a gray well in place of the moving column.
g.setColor(table.getParent().getBackground());
g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
vacatedColumnRect.width, vacatedColumnRect.height);
// Move to the where the cell has been dragged.
vacatedColumnRect.x += distance;
// Fill the background.
g.setColor(table.getBackground());
g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
vacatedColumnRect.width, vacatedColumnRect.height);
// Paint the vertical grid lines if necessary.
if (table.getShowVerticalLines()) {
g.setColor(table.getGridColor());
int x1 = vacatedColumnRect.x;
int y1 = vacatedColumnRect.y;
int x2 = x1 + vacatedColumnRect.width - 1;
int y2 = y1 + vacatedColumnRect.height - 1;
// Left
g.drawLine(x1-1, y1, x1-1, y2);
// Right
g.drawLine(x2, y1, x2, y2);
}
for(int row = rMin; row <= rMax; row++) {
// Render the cell value
Rectangle r = table.getCellRect(row, draggedColumnIndex, false);
r.x += distance;
paintCell(g, r, row, draggedColumnIndex);
// Paint the (lower) horizontal grid line if necessary.
if (table.getShowHorizontalLines()) {
g.setColor(table.getGridColor());
Rectangle rcr = table.getCellRect(row, draggedColumnIndex, true);
rcr.x += distance;
int x1 = rcr.x;
int y1 = rcr.y;
int x2 = x1 + rcr.width - 1;
int y2 = y1 + rcr.height - 1;
g.drawLine(x1, y2, x2, y2);
}
}
}
private int viewIndexForColumn(TableColumn aColumn) {
TableColumnModel cm = table.getColumnModel();
for (int column = 0; column < cm.getColumnCount(); column++) {
if (cm.getColumn(column) == aColumn) {
return column;
}
}
return -1;
}
private Rectangle extendRect(Rectangle rect, boolean horizontal) {
if (rect == null) {
return rect;
}
if (horizontal) {
rect.x = 0;
rect.width = table.getWidth();
} else {
rect.y = 0;
if (table.getRowCount() != 0) {
Rectangle lastRect = table.getCellRect(table.getRowCount() - 1, 0, true);
rect.height = lastRect.y + lastRect.height;
} else {
rect.height = table.getHeight();
}
}
return rect;
}
private Rectangle getVDropLineRect(JTable.DropLocation loc) {
if (!loc.isInsertColumn()) {
return null;
}
boolean ltr = table.getComponentOrientation().isLeftToRight();
int col = loc.getColumn();
Rectangle rect = table.getCellRect(loc.getRow(), col, true);
if (col >= table.getColumnCount()) {
col--;
rect = table.getCellRect(loc.getRow(), col, true);
if (ltr) {
rect.x = rect.x + rect.width;
}
} else if (!ltr) {
rect.x = rect.x + rect.width;
}
if (rect.x == 0) {
rect.x = -1;
} else {
rect.x -= 2;
}
rect.width = 3;
return rect;
}
}
// End of Class BasicTableUI

  测试代码:

Java代码 复制代码  收藏代码
  1. import java.awt.BorderLayout;   
  2. import java.awt.event.ActionEvent;   
  3. import java.awt.event.ActionListener;   
  4.   
  5. import javax.swing.JButton;   
  6. import javax.swing.JFrame;   
  7. import javax.swing.JScrollPane;   
  8. import javax.swing.table.DefaultTableModel;   
  9.   
  10. import com.jrf.jgrid.guitools.gridbagtable.GridBagTable;   
  11.   
  12.   
  13. public class Test implements ActionListener{   
  14.        
  15.     GridBagTable table;   
  16.     public Test()   
  17.     {   
  18.         JFrame d = new JFrame();   
  19.         DefaultTableModel model = new DefaultTableModel(5,5);   
  20.            
  21.         table = new GridBagTable(model);   
  22.         table.setRowHeight(20);   
  23.            
  24.         JScrollPane pane = new JScrollPane(table);   
  25.         d.getContentPane().add(pane, BorderLayout.CENTER);   
  26.         JButton btn = new JButton("合并/拆分");   
  27.         d.getContentPane().add(btn, BorderLayout.NORTH);   
  28.         btn.addActionListener(this);   
  29.         d.setBounds(00400400);   
  30.         d.setVisible(true);   
  31.     }   
  32.        
  33.     public static void main(String[] fsd){   
  34.         new Test();   
  35.     }   
  36.        
  37.     public void actionPerformed(ActionEvent e) {   
  38.         table.mergeCells(table.getSelectedRows(), table.getSelectedColumns());   
  39.     }   
  40. }  年前在网上参加了一个JavaSwing的招聘上机考试。招聘方要求开发一个类似EXCEL支持单元格合并的JTable。差不多用了5天的时间提交代码,最后被告知测试通过,我提出是否可做兼职,对方回复需要到上海做全职开发,最后也就放弃了。最近公司的一个项目中需要用到以前的代码,偶又重构了一次,设计思想来源于ListSelectionModel。

     



    GridBagModel:抽象模型接口。该接口用于描述表格中单元格的合并状态。
    DefaultGridBagTableModel:GridBagModel的默认实现。
    GridBagTable:继承自JTable的控制器。通过该类中的方法控制表格单元的合并和拆分。
    GridBagTableUI:GridBagTable对应的UI。

    TODO:(已合并)行、列的插入,删除操作对应的GridBagModel的修改,不过已留接口。

    Java代码 复制代码  收藏代码
    1. package org.dxj.guitools.gridbagtable;   
    2. import java.awt.Component;   
    3. import java.awt.Point;   
    4. import java.awt.Rectangle;   
    5. import java.util.Enumeration;   
    6. import java.util.EventObject;   
    7.   
    8. import javax.swing.DefaultCellEditor;   
    9. import javax.swing.JTable;   
    10. import javax.swing.SwingUtilities;   
    11. import javax.swing.event.TableModelEvent;   
    12. import javax.swing.table.AbstractTableModel;   
    13. import javax.swing.table.TableColumn;   
    14. import javax.swing.table.TableColumnModel;   
    15.   
    16. /**  
    17.  * @author 15860102@qq.com  
    18.  */  
    19. public class GridBagTable extends JTable{   
    20.   
    21.     GridBagModel gridBagModel;   
    22.        
    23.     public GridBagModel getGridBagModel() {   
    24.         return gridBagModel;   
    25.     }   
    26.        
    27.     public void setGridBagModel(GridBagModel gridBagModel){   
    28.         if( gridBagModel != null && gridBagModel != this.gridBagModel )   
    29.             this.gridBagModel = gridBagModel;   
    30.     }   
    31.   
    32.     public GridBagTable(AbstractTableModel dm){   
    33.         super(dm);         
    34.         getTableHeader().setReorderingAllowed(false);   
    35.         gridBagModel = new DefaultGridBagTableModel(dm);           
    36.         getColumnModel().setColumnSelectionAllowed(true);   
    37.     }   
    38.        
    39.      private void updateSubComponentUI(Object componentShell) {   
    40.         if (componentShell == null) {   
    41.             return;   
    42.         }   
    43.         Component component = null;   
    44.         if (componentShell instanceof Component) {   
    45.             component = (Component)componentShell;   
    46.         }   
    47.         if (componentShell instanceof DefaultCellEditor) {   
    48.             component = ((DefaultCellEditor)componentShell).getComponent();   
    49.         }   
    50.   
    51.         if (component != null) {   
    52.             SwingUtilities.updateComponentTreeUI(component);   
    53.         }   
    54.     }   
    55.        
    56.     public void updateUI() {       
    57.         // Update the UIs of the cell renderers, cell editors and header renderers.   
    58.         TableColumnModel cm = getColumnModel();   
    59.         for(int column = 0; column < cm.getColumnCount(); column++) {   
    60.             TableColumn aColumn = cm.getColumn(column);   
    61.         updateSubComponentUI(aColumn.getCellRenderer());   
    62.             updateSubComponentUI(aColumn.getCellEditor());   
    63.         updateSubComponentUI(aColumn.getHeaderRenderer());   
    64.         }   
    65.   
    66.         // Update the UIs of all the default renderers.   
    67.         Enumeration defaultRenderers = defaultRenderersByColumnClass.elements();   
    68.         while (defaultRenderers.hasMoreElements()) {   
    69.             updateSubComponentUI(defaultRenderers.nextElement());   
    70.         }   
    71.   
    72.         // Update the UIs of all the default editors.   
    73.         Enumeration defaultEditors = defaultEditorsByColumnClass.elements();   
    74.         while (defaultEditors.hasMoreElements()) {   
    75.             updateSubComponentUI(defaultEditors.nextElement());   
    76.         }   
    77.   
    78.         // Update the UI of the table header   
    79.         if (tableHeader != null && tableHeader.getParent() == null) {   
    80.             tableHeader.updateUI();   
    81.         }   
    82.         setUI(new GridBagTableUI());   
    83.     }   
    84.        
    85.     public Rectangle getGridCellRect(int row, int column, boolean includeSpacing){   
    86.         return super.getCellRect(row, column, includeSpacing);   
    87.     }   
    88.        
    89.     public Rectangle getCellRect(int row, int column, boolean includeSpacing) {        
    90.         Rectangle cellRect = super.getCellRect(row, column, includeSpacing);   
    91.         int cols = gridBagModel.getColumnGrid(row, column);   
    92.         TableColumnModel cm = getColumnModel();   
    93.         forint n=1; n<cols; n++)   
    94.             cellRect.width += cm.getColumn(column+n).getWidth();   
    95.         int rows = gridBagModel.getRowGrid(row, column);   
    96.         forint n=1; n<rows; n++)   
    97.             cellRect.height += getRowHeight(row+n);   
    98.         return cellRect;            
    99.     }   
    100.        
    101.     public void tableChanged(TableModelEvent e){   
    102.         super.tableChanged(e);   
    103.         //TODO   
    104.     }   
    105.        
    106.     public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn){   
    107.         if( gridBagModel.mergeCells(startRow, endRow, startColumn, endColumn)){   
    108.             repaint();   
    109.             return true;   
    110.         }      
    111.         return false;   
    112.     }   
    113.         
    114.     public boolean mergeCells(int[] rows, int[] columns){   
    115.         if( gridBagModel.mergeCells(rows, columns)){   
    116.             repaint();   
    117.             return true;   
    118.         }      
    119.         return false;   
    120.     }   
    121.        
    122.     public boolean spliteCellAt(int row, int column){   
    123.         if( gridBagModel.spliteCellAt(row, column)){   
    124.             repaint();   
    125.             return true;   
    126.         }   
    127.         return false;   
    128.     }   
    129.        
    130.     public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {   
    131.         if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED  )   
    132.             super.changeSelection(rowIndex, columnIndex, toggle, extend);   
    133.         Point p;   
    134.         forint row = rowIndex; row >= 0; row-- ){   
    135.             forint col = columnIndex; col >= 0; col-- ){   
    136.                 p = gridBagModel.getGrid(row, col);   
    137.                 //p = ((Point)((Vector)rowVector.get(row)).get(col));   
    138.                 if( col + p.x > columnIndex && row + p.y > rowIndex){   
    139.                     rowIndex = row;   
    140.                     columnIndex = col;   
    141.                     break;   
    142.                 }   
    143.             }   
    144.         }      
    145.         super.changeSelection(rowIndex, columnIndex, toggle, extend);   
    146.         repaint();   
    147.     }   
    148.        
    149.     public boolean editCellAt(int rowIndex, int columnIndex, EventObject e){   
    150.         if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED  )   
    151.             return super.editCellAt(rowIndex, columnIndex, e);      
    152.         Point p;   
    153.         forint row = rowIndex; row >= 0; row-- ){   
    154.             forint col = columnIndex; col >= 0; col-- ){   
    155.                 p = gridBagModel.getGrid(row, col);   
    156.                 if( col + p.x > columnIndex && row + p.y > rowIndex){   
    157.                     rowIndex = row;   
    158.                     columnIndex = col;   
    159.                     break;   
    160.                 }   
    161.             }   
    162.         }          
    163.         return super.editCellAt(rowIndex, columnIndex, e);           
    164.     }   
    165. }  
    package org.dxj.guitools.gridbagtable;
    import java.awt.Component;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.util.Enumeration;
    import java.util.EventObject;
    import javax.swing.DefaultCellEditor;
    import javax.swing.JTable;
    import javax.swing.SwingUtilities;
    import javax.swing.event.TableModelEvent;
    import javax.swing.table.AbstractTableModel;
    import javax.swing.table.TableColumn;
    import javax.swing.table.TableColumnModel;
    /**
    * @author 15860102@qq.com
    */
    public class GridBagTable extends JTable{
    GridBagModel gridBagModel;
    public GridBagModel getGridBagModel() {
    return gridBagModel;
    }
    public void setGridBagModel(GridBagModel gridBagModel){
    if( gridBagModel != null && gridBagModel != this.gridBagModel )
    this.gridBagModel = gridBagModel;
    }
    public GridBagTable(AbstractTableModel dm){
    super(dm);
    getTableHeader().setReorderingAllowed(false);
    gridBagModel = new DefaultGridBagTableModel(dm);
    getColumnModel().setColumnSelectionAllowed(true);
    }
    private void updateSubComponentUI(Object componentShell) {
    if (componentShell == null) {
    return;
    }
    Component component = null;
    if (componentShell instanceof Component) {
    component = (Component)componentShell;
    }
    if (componentShell instanceof DefaultCellEditor) {
    component = ((DefaultCellEditor)componentShell).getComponent();
    }
    if (component != null) {
    SwingUtilities.updateComponentTreeUI(component);
    }
    }
    public void updateUI() {
    // Update the UIs of the cell renderers, cell editors and header renderers.
    TableColumnModel cm = getColumnModel();
    for(int column = 0; column < cm.getColumnCount(); column++) {
    TableColumn aColumn = cm.getColumn(column);
    updateSubComponentUI(aColumn.getCellRenderer());
    updateSubComponentUI(aColumn.getCellEditor());
    updateSubComponentUI(aColumn.getHeaderRenderer());
    }
    // Update the UIs of all the default renderers.
    Enumeration defaultRenderers = defaultRenderersByColumnClass.elements();
    while (defaultRenderers.hasMoreElements()) {
    updateSubComponentUI(defaultRenderers.nextElement());
    }
    // Update the UIs of all the default editors.
    Enumeration defaultEditors = defaultEditorsByColumnClass.elements();
    while (defaultEditors.hasMoreElements()) {
    updateSubComponentUI(defaultEditors.nextElement());
    }
    // Update the UI of the table header
    if (tableHeader != null && tableHeader.getParent() == null) {
    tableHeader.updateUI();
    }
    setUI(new GridBagTableUI());
    }
    public Rectangle getGridCellRect(int row, int column, boolean includeSpacing){
    return super.getCellRect(row, column, includeSpacing);
    }
    public Rectangle getCellRect(int row, int column, boolean includeSpacing) {
    Rectangle cellRect = super.getCellRect(row, column, includeSpacing);
    int cols = gridBagModel.getColumnGrid(row, column);
    TableColumnModel cm = getColumnModel();
    for( int n=1; n<cols; n++)
    cellRect.width += cm.getColumn(column+n).getWidth();
    int rows = gridBagModel.getRowGrid(row, column);
    for( int n=1; n<rows; n++)
    cellRect.height += getRowHeight(row+n);
    return cellRect;
    }
    public void tableChanged(TableModelEvent e){
    super.tableChanged(e);
    //TODO
    }
    public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn){
    if( gridBagModel.mergeCells(startRow, endRow, startColumn, endColumn)){
    repaint();
    return true;
    }
    return false;
    }
    public boolean mergeCells(int[] rows, int[] columns){
    if( gridBagModel.mergeCells(rows, columns)){
    repaint();
    return true;
    }
    return false;
    }
    public boolean spliteCellAt(int row, int column){
    if( gridBagModel.spliteCellAt(row, column)){
    repaint();
    return true;
    }
    return false;
    }
    public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
    if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED
    )
    super.changeSelection(rowIndex, columnIndex, toggle, extend);
    Point p;
    for( int row = rowIndex; row >= 0; row-- ){
    for( int col = columnIndex; col >= 0; col-- ){
    p = gridBagModel.getGrid(row, col);
    //p = ((Point)((Vector)rowVector.get(row)).get(col));
    if( col + p.x > columnIndex && row + p.y > rowIndex){
    rowIndex = row;
    columnIndex = col;
    break;
    }
    }
    }
    super.changeSelection(rowIndex, columnIndex, toggle, extend);
    repaint();
    }
    public boolean editCellAt(int rowIndex, int columnIndex, EventObject e){
    if( gridBagModel.getCellState( rowIndex , columnIndex ) != GridBagModel.COVERED
    )
    return super.editCellAt(rowIndex, columnIndex, e);
    Point p;
    for( int row = rowIndex; row >= 0; row-- ){
    for( int col = columnIndex; col >= 0; col-- ){
    p = gridBagModel.getGrid(row, col);
    if( col + p.x > columnIndex && row + p.y > rowIndex){
    rowIndex = row;
    columnIndex = col;
    break;
    }
    }
    }
    return super.editCellAt(rowIndex, columnIndex, e);
    }
    }
    
     
    Java代码 复制代码  收藏代码
    1. package org.dxj.guitools.gridbagtable;   
    2.   
    3. import java.awt.Point;   
    4.   
    5. public interface GridBagModel {   
    6.     //格子处于正常状态   
    7.     int DEFAULT = 0;   
    8.     //格子合并了其他的格子   
    9.     int MERGE = 1;   
    10.     //格子被其他格子合并   
    11.     int COVERED = -1;   
    12.        
    13.     /**  
    14.      * @param row 行  
    15.      * @param column 列  
    16.      * @return 该单元格在行、列的跨度  
    17.      */  
    18.     Point getGrid(int row, int column);   
    19.        
    20.     /**  
    21.      * 在Y轴方向的跨度  
    22.      * @param row  
    23.      * @param column  
    24.      * @return  
    25.      */  
    26.     int getRowGrid(int row, int column);   
    27.        
    28.     /**  
    29.      * 在X轴方向的跨度  
    30.      * @param row  
    31.      * @param column  
    32.      * @return  
    33.      */  
    34.     int getColumnGrid(int row, int column);   
    35.   
    36.     /**  
    37.      * @param rows 行集合  
    38.      * @param columns 列集合  
    39.      * @return 单元格集合是否可以合并在一起  
    40.      */  
    41.     boolean canMergeCells(int[] rows, int[] columns);   
    42.        
    43.     /**  
    44.      * 判断该单元格状态  
    45.      * @param row  
    46.      * @param column  
    47.      * @return MERGE|DEFAULT|COVERED  
    48.      */  
    49.     int getCellState(int row, int column);   
    50.        
    51.     /**  
    52.      * 将单元格集合合并  
    53.      * @param startRow 开始行  
    54.      * @param endRow 结束行  
    55.      * @param startColumn 开始列  
    56.      * @param endColumn 结束列  
    57.      * @return 是否合并成功  
    58.      */  
    59.     boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn);   
    60.        
    61.     /**  
    62.      * 将单元格集合合并  
    63.      * @param rows 行集合  
    64.      * @param columns 列集合  
    65.      * @return 是否合并成功  
    66.      */  
    67.     boolean mergeCells(int[] rows, int[] columns);   
    68.        
    69.     /**  
    70.      * 拆分单元格  
    71.      * @param row 行  
    72.      * @param column 列  
    73.      * @return 是否拆分成功  
    74.      */  
    75.     boolean spliteCellAt(int row, int column);   
    76.        
    77.     /**  
    78.      * 清除 所有合并  
    79.      */  
    80.     void clearMergence();   
    81. }  
    package org.dxj.guitools.gridbagtable;
    import java.awt.Point;
    public interface GridBagModel {
    //格子处于正常状态
    int DEFAULT = 0;
    //格子合并了其他的格子
    int MERGE = 1;
    //格子被其他格子合并
    int COVERED = -1;
    /**
    * @param row 行
    * @param column 列
    * @return 该单元格在行、列的跨度
    */
    Point getGrid(int row, int column);
    /**
    * 在Y轴方向的跨度
    * @param row
    * @param column
    * @return
    */
    int getRowGrid(int row, int column);
    /**
    * 在X轴方向的跨度
    * @param row
    * @param column
    * @return
    */
    int getColumnGrid(int row, int column);
    /**
    * @param rows 行集合
    * @param columns 列集合
    * @return 单元格集合是否可以合并在一起
    */
    boolean canMergeCells(int[] rows, int[] columns);
    /**
    * 判断该单元格状态
    * @param row
    * @param column
    * @return MERGE|DEFAULT|COVERED
    */
    int getCellState(int row, int column);
    /**
    * 将单元格集合合并
    * @param startRow 开始行
    * @param endRow 结束行
    * @param startColumn 开始列
    * @param endColumn 结束列
    * @return 是否合并成功
    */
    boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn);
    /**
    * 将单元格集合合并
    * @param rows 行集合
    * @param columns 列集合
    * @return 是否合并成功
    */
    boolean mergeCells(int[] rows, int[] columns);
    /**
    * 拆分单元格
    * @param row 行
    * @param column 列
    * @return 是否拆分成功
    */
    boolean spliteCellAt(int row, int column);
    /**
    * 清除 所有合并
    */
    void clearMergence();
    }
    
     
    Java代码 复制代码  收藏代码
    1. package org.dxj.guitools.gridbagtable;   
    2.   
    3. import java.awt.Point;   
    4. import java.util.Arrays;   
    5. import java.util.List;   
    6. import java.util.Vector;   
    7.   
    8. import javax.swing.event.TableModelEvent;   
    9. import javax.swing.event.TableModelListener;   
    10. import javax.swing.table.AbstractTableModel;   
    11.   
    12. public class DefaultGridBagTableModel implements GridBagModel, TableModelListener{   
    13.     protected AbstractTableModel model;   
    14.     protected List<List<Point>> gridInfo;   
    15.        
    16.     DefaultGridBagTableModel(AbstractTableModel model){   
    17.         gridInfo = new Vector<List<Point>>();   
    18.         setTableModel(model);   
    19.     }   
    20.        
    21.     public void setTableModel(AbstractTableModel model){   
    22.         if( model != null && model != this.model ){   
    23.             ifthis.model != null )   
    24.                 this.model.removeTableModelListener(this);   
    25.             //防止多次添加监听器   
    26.             model.removeTableModelListener(this);   
    27.             model.addTableModelListener(this);   
    28.             this.model = model;   
    29.             clearMergence();   
    30.         }   
    31.     }   
    32.        
    33.     public void clearMergence(){   
    34.         if( gridInfo == null  )   
    35.             gridInfo = new Vector<List<Point>>();   
    36.         else  
    37.             gridInfo.clear();   
    38.            
    39.         if( model == null )   
    40.             return;   
    41.            
    42.         //初始化,每个格子占的格子数为(1,1);   
    43.         for(int row=model.getRowCount(); --row>=0;){   
    44.             List<Point> infos = new Vector<Point>();   
    45.             gridInfo.add(infos);   
    46.             for(int col=model.getColumnCount(); --col>=0;){   
    47.                 infos.add(getDefaultPoint());   
    48.             }   
    49.         }   
    50.     }   
    51.        
    52.     public Point getDefaultPoint(){   
    53.         return new Point(1,1);   
    54.     }   
    55.        
    56.     @Override  
    57.     public boolean canMergeCells(int[] rows, int[] columns) {   
    58.         if( rows == null || columns == null ) return false;   
    59.         Arrays.sort(rows);   
    60.         for(int index=0; index<rows.length-1; index++){   
    61.             if( rows[index+1] - rows[index] > 1 )   
    62.                 return false;   
    63.         }   
    64.         Arrays.sort(columns);   
    65.         for(int index=0; index<columns.length-1; index++){   
    66.             if( columns[index+1] - columns[index] > 1 )   
    67.                 return false;   
    68.         }   
    69.         return true;   
    70.     }   
    71.        
    72.     @Override  
    73.     public int getCellState(int row, int column) {   
    74.         Point grid = getGrid(row, column);   
    75.         if( grid == null ) return DEFAULT;   
    76.         if( grid.x>1 || grid.y>1 )   
    77.             return MERGE;   
    78.         if( grid.x<=0 || grid.y<=0 )   
    79.             return COVERED;   
    80.         return DEFAULT;   
    81.     }   
    82.   
    83.     @Override  
    84.     public int getColumnGrid(int row, int column) {   
    85.         if( gridInfo != null && row >=0 && row < gridInfo.size() ){   
    86.             List<Point> gridRow = gridInfo.get(row);   
    87.             if( gridRow != null && column >=0 && column < gridRow.size() ){   
    88.                 Point point = gridRow.get(column);   
    89.                 if( point != null )   
    90.                     return point.x;   
    91.             }      
    92.         }   
    93.         return 1;   
    94.     }   
    95.   
    96.     @Override  
    97.     public Point getGrid(int row, int column) {   
    98.         if( gridInfo != null && row >=0 && row < gridInfo.size() ){   
    99.             List<Point> gridRow = gridInfo.get(row);   
    100.             if( gridRow != null && column >=0 && column < gridRow.size() ){   
    101.                 return gridRow.get(column);   
    102.             }      
    103.         }   
    104.         return getDefaultPoint();   
    105.     }   
    106.   
    107.     @Override  
    108.     public int getRowGrid(int row, int column) {   
    109.         if( gridInfo != null && row >=0 && row < gridInfo.size() ){   
    110.             List<Point> gridRow = gridInfo.get(row);   
    111.             if( gridRow != null && column >=0 && column < gridRow.size() ){   
    112.                 Point point = gridRow.get(column);   
    113.                 if( point != null )   
    114.                     return point.y;   
    115.             }      
    116.         }   
    117.         return 1;   
    118.     }   
    119.   
    120.     protected boolean setGrid(int row, int column, Point grid) {   
    121.         if( gridInfo != null && row >=0 && row < gridInfo.size() ){   
    122.             List<Point> gridRow = gridInfo.get(row);   
    123.             if( gridRow != null && column >=0 && column < gridRow.size() ){   
    124.                 Point point = gridRow.get(column);   
    125.                 if( point != null ){   
    126.                     point.setLocation(grid);   
    127.                 }   
    128.                 else{   
    129.                     gridRow.set(column, grid.getLocation());   
    130.                 }   
    131.                 return true;   
    132.             }      
    133.         }   
    134.         return false;   
    135.     }   
    136.   
    137.     @Override  
    138.     public boolean spliteCellAt(int row, int column) {   
    139.         if( gridInfo != null && row >=0 && row < gridInfo.size() ){   
    140.             List<Point> gridRow = gridInfo.get(row);   
    141.             if( gridRow != null && column >=0 && column < gridRow.size() ){   
    142.                 Point point = gridRow.get(column);   
    143.                 if( point != null ){   
    144.                     point = point.getLocation();   
    145.                     for(int a=0; a<point.y; a++){   
    146.                         for(int b=0; b<point.x; b++){   
    147.                             setGrid(row+a, column+b, getDefaultPoint());   
    148.                         }   
    149.                     }   
    150.                 }   
    151.                 else{   
    152.                     gridRow.set(column, getDefaultPoint());   
    153.                 }   
    154.                 return true;   
    155.             }      
    156.         }   
    157.         return false;   
    158.     }   
    159.        
    160.     @Override  
    161.     /**  
    162.      * table中发生行的添加和删除的时候需要修改该模型  
    163.      */  
    164.     public void tableChanged(TableModelEvent e) {   
    165.         //TODO   
    166.     }   
    167.        
    168.     @Override  
    169.     public boolean mergeCells(int[] rows, int[] columns) {   
    170.         if( !canMergeCells(rows, columns) )   
    171.             return false;   
    172.         Arrays.sort(rows);   
    173.         Arrays.sort(columns);   
    174.         return mergeCells(rows[0],rows[rows.length-1],columns[0],columns[columns.length-1]);   
    175.     }   
    176.   
    177.     @Override  
    178.     public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn) {   
    179.         setGrid(startRow, startColumn, new Point(endColumn-startColumn+1, endRow-startRow+1));    
    180.         for(int row=startRow; row<=endRow; row++){   
    181.             for(int col=startColumn; col<=endColumn; col++){   
    182.                 if(row==startRow&&col==startColumn)   
    183.                     continue;   
    184.                 else  
    185.                     setGrid(row, col, new Point(COVERED,COVERED));    
    186.             }   
    187.         }   
    188.         return true;   
    189.     }   
    190.        
    191.     public String toString(){   
    192.         if( gridInfo == null )   
    193.             return "";   
    194.         StringBuffer sb = new StringBuffer();   
    195.         for(List<Point> rowInfo : gridInfo ){   
    196.             for(Point grid : rowInfo){   
    197.                 sb.append("["+grid.x+","+grid.y+"], ");   
    198.             }   
    199.             sb.append("n");   
    200.         }   
    201.         return sb.toString();   
    202.     }   
    203. }  
    package org.dxj.guitools.gridbagtable;
    import java.awt.Point;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Vector;
    import javax.swing.event.TableModelEvent;
    import javax.swing.event.TableModelListener;
    import javax.swing.table.AbstractTableModel;
    public class DefaultGridBagTableModel implements GridBagModel, TableModelListener{
    protected AbstractTableModel model;
    protected List<List<Point>> gridInfo;
    DefaultGridBagTableModel(AbstractTableModel model){
    gridInfo = new Vector<List<Point>>();
    setTableModel(model);
    }
    public void setTableModel(AbstractTableModel model){
    if( model != null && model != this.model ){
    if( this.model != null )
    this.model.removeTableModelListener(this);
    //防止多次添加监听器
    model.removeTableModelListener(this);
    model.addTableModelListener(this);
    this.model = model;
    clearMergence();
    }
    }
    public void clearMergence(){
    if( gridInfo == null
    )
    gridInfo = new Vector<List<Point>>();
    else
    gridInfo.clear();
    if( model == null )
    return;
    //初始化,每个格子占的格子数为(1,1);
    for(int row=model.getRowCount(); --row>=0;){
    List<Point> infos = new Vector<Point>();
    gridInfo.add(infos);
    for(int col=model.getColumnCount(); --col>=0;){
    infos.add(getDefaultPoint());
    }
    }
    }
    public Point getDefaultPoint(){
    return new Point(1,1);
    }
    @Override
    public boolean canMergeCells(int[] rows, int[] columns) {
    if( rows == null || columns == null ) return false;
    Arrays.sort(rows);
    for(int index=0; index<rows.length-1; index++){
    if( rows[index+1] - rows[index] > 1 )
    return false;
    }
    Arrays.sort(columns);
    for(int index=0; index<columns.length-1; index++){
    if( columns[index+1] - columns[index] > 1 )
    return false;
    }
    return true;
    }
    @Override
    public int getCellState(int row, int column) {
    Point grid = getGrid(row, column);
    if( grid == null ) return DEFAULT;
    if( grid.x>1 || grid.y>1 )
    return MERGE;
    if( grid.x<=0 || grid.y<=0 )
    return COVERED;
    return DEFAULT;
    }
    @Override
    public int getColumnGrid(int row, int column) {
    if( gridInfo != null && row >=0 && row < gridInfo.size() ){
    List<Point> gridRow = gridInfo.get(row);
    if( gridRow != null && column >=0 && column < gridRow.size() ){
    Point point = gridRow.get(column);
    if( point != null )
    return point.x;
    }
    }
    return 1;
    }
    @Override
    public Point getGrid(int row, int column) {
    if( gridInfo != null && row >=0 && row < gridInfo.size() ){
    List<Point> gridRow = gridInfo.get(row);
    if( gridRow != null && column >=0 && column < gridRow.size() ){
    return gridRow.get(column);
    }
    }
    return getDefaultPoint();
    }
    @Override
    public int getRowGrid(int row, int column) {
    if( gridInfo != null && row >=0 && row < gridInfo.size() ){
    List<Point> gridRow = gridInfo.get(row);
    if( gridRow != null && column >=0 && column < gridRow.size() ){
    Point point = gridRow.get(column);
    if( point != null )
    return point.y;
    }
    }
    return 1;
    }
    protected boolean setGrid(int row, int column, Point grid) {
    if( gridInfo != null && row >=0 && row < gridInfo.size() ){
    List<Point> gridRow = gridInfo.get(row);
    if( gridRow != null && column >=0 && column < gridRow.size() ){
    Point point = gridRow.get(column);
    if( point != null ){
    point.setLocation(grid);
    }
    else{
    gridRow.set(column, grid.getLocation());
    }
    return true;
    }
    }
    return false;
    }
    @Override
    public boolean spliteCellAt(int row, int column) {
    if( gridInfo != null && row >=0 && row < gridInfo.size() ){
    List<Point> gridRow = gridInfo.get(row);
    if( gridRow != null && column >=0 && column < gridRow.size() ){
    Point point = gridRow.get(column);
    if( point != null ){
    point = point.getLocation();
    for(int a=0; a<point.y; a++){
    for(int b=0; b<point.x; b++){
    setGrid(row+a, column+b, getDefaultPoint());
    }
    }
    }
    else{
    gridRow.set(column, getDefaultPoint());
    }
    return true;
    }
    }
    return false;
    }
    @Override
    /**
    * table中发生行的添加和删除的时候需要修改该模型
    */
    public void tableChanged(TableModelEvent e) {
    //TODO
    }
    @Override
    public boolean mergeCells(int[] rows, int[] columns) {
    if( !canMergeCells(rows, columns) )
    return false;
    Arrays.sort(rows);
    Arrays.sort(columns);
    return mergeCells(rows[0],rows[rows.length-1],columns[0],columns[columns.length-1]);
    }
    @Override
    public boolean mergeCells(int startRow, int endRow, int startColumn, int endColumn) {
    setGrid(startRow, startColumn, new Point(endColumn-startColumn+1, endRow-startRow+1));
    for(int row=startRow; row<=endRow; row++){
    for(int col=startColumn; col<=endColumn; col++){
    if(row==startRow&&col==startColumn)
    continue;
    else
    setGrid(row, col, new Point(COVERED,COVERED));
    }
    }
    return true;
    }
    public String toString(){
    if( gridInfo == null )
    return "";
    StringBuffer sb = new StringBuffer();
    for(List<Point> rowInfo : gridInfo ){
    for(Point grid : rowInfo){
    sb.append("["+grid.x+","+grid.y+"], ");
    }
    sb.append("n");
    }
    return sb.toString();
    }
    }
    
     
    Java代码 复制代码  收藏代码
    1. package org.dxj.guitools.gridbagtable;   
    2.   
    3. import java.awt.Color;   
    4. import java.awt.Component;   
    5. import java.awt.Dimension;   
    6. import java.awt.Graphics;   
    7. import java.awt.Point;   
    8. import java.awt.Rectangle;   
    9. import java.util.Enumeration;   
    10.   
    11. import javax.swing.BorderFactory;   
    12. import javax.swing.JComponent;   
    13. import javax.swing.JTable;   
    14. import javax.swing.UIManager;   
    15. import javax.swing.plaf.basic.BasicTableUI;   
    16. import javax.swing.table.JTableHeader;   
    17. import javax.swing.table.TableCellRenderer;   
    18. import javax.swing.table.TableColumn;   
    19. import javax.swing.table.TableColumnModel;   
    20.   
    21. public class GridBagTableUI extends BasicTableUI   
    22. {   
    23.     public Dimension getPreferredSize(JComponent c) {   
    24.         long width = 0;   
    25.         Enumeration<TableColumn> enumeration = table.getColumnModel().getColumns();   
    26.         while (enumeration.hasMoreElements()) {   
    27.             TableColumn aColumn = (TableColumn)enumeration.nextElement();   
    28.             width = width + aColumn.getPreferredWidth();   
    29.         }   
    30.         return createTableSize(width);   
    31.     }   
    32.        
    33.     private Dimension createTableSize(long width) {   
    34.         int height = 0;   
    35.         int rowCount = table.getRowCount();   
    36.         if (rowCount > 0 && table.getColumnCount() > 0) {   
    37.             Rectangle r = table.getCellRect(rowCount-10true);   
    38.             height = r.y + r.height;   
    39.         }   
    40.         // Width is always positive. The call to abs() is a workaround for   
    41.         // a bug in the 1.1.6 JIT on Windows.   
    42.         long tmp = Math.abs(width);   
    43.             if (tmp > Integer.MAX_VALUE) {   
    44.                 tmp = Integer.MAX_VALUE;   
    45.             }   
    46.         return new Dimension((int)tmp, height);   
    47.         }   
    48.        
    49.     public void paint(Graphics g, JComponent c) {   
    50.         Rectangle clip = g.getClipBounds();   
    51.   
    52.         Rectangle bounds = table.getBounds();   
    53.         // account for the fact that the graphics has already been translated   
    54.         // into the table's bounds   
    55.         bounds.x = bounds.y = 0;   
    56.   
    57.     if (table.getRowCount() <= 0 || table.getColumnCount() <= 0 ||   
    58.                 // this check prevents us from painting the entire table   
    59.                 // when the clip doesn't intersect our bounds at all   
    60.                 !bounds.intersects(clip)) {   
    61.   
    62.             paintDropLines(g);   
    63.         return;   
    64.     }   
    65.   
    66.         boolean ltr = table.getComponentOrientation().isLeftToRight();   
    67.   
    68.     Point upperLeft = clip.getLocation();   
    69.         if (!ltr) {   
    70.             upperLeft.x++;   
    71.         }   
    72.   
    73.     Point lowerRight = new Point(clip.x + clip.width - (ltr ? 1 : 0),   
    74.                                      clip.y + clip.height);   
    75.   
    76.         int rMin = table.rowAtPoint(upperLeft);   
    77.         int rMax = table.rowAtPoint(lowerRight);   
    78.         // This should never happen (as long as our bounds intersect the clip,   
    79.         // which is why we bail above if that is the case).   
    80.         if (rMin == -1) {   
    81.         rMin = 0;   
    82.         }   
    83.         // If the table does not have enough rows to fill the view we'll get -1.   
    84.         // (We could also get -1 if our bounds don't intersect the clip,   
    85.         // which is why we bail above if that is the case).   
    86.         // Replace this with the index of the last row.   
    87.         if (rMax == -1) {   
    88.         rMax = table.getRowCount()-1;   
    89.         }   
    90.   
    91.         int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);    
    92.         int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);           
    93.         // This should never happen.   
    94.         if (cMin == -1) {   
    95.         cMin = 0;   
    96.         }   
    97.     // If the table does not have enough columns to fill the view we'll get -1.   
    98.         // Replace this with the index of the last column.   
    99.         if (cMax == -1) {   
    100.         cMax = table.getColumnCount()-1;   
    101.         }   
    102.   
    103.         // Paint the grid.   
    104.         //paintGrid(g, rMin, rMax, cMin, cMax);   
    105.   
    106.         // Paint the cells.   
    107.     paintCells(g, rMin, rMax, cMin, cMax);   
    108.   
    109.         paintDropLines(g);   
    110.     }   
    111.        
    112.     private void paintDropLines(Graphics g) {   
    113.         JTable.DropLocation loc = table.getDropLocation();   
    114.         if (loc == null) {   
    115.             return;   
    116.         }   
    117.   
    118.         Color color = UIManager.getColor("Table.dropLineColor");   
    119.         Color shortColor = UIManager.getColor("Table.dropLineShortColor");   
    120.         if (color == null && shortColor == null) {   
    121.             return;   
    122.         }   
    123.   
    124.         Rectangle rect;   
    125.   
    126.         rect = getHDropLineRect(loc);   
    127.         if (rect != null) {   
    128.             int x = rect.x;   
    129.             int w = rect.width;   
    130.             if (color != null) {   
    131.                 extendRect(rect, true);   
    132.                 g.setColor(color);   
    133.                 g.fillRect(rect.x, rect.y, rect.width, rect.height);   
    134.             }   
    135.             if (!loc.isInsertColumn() && shortColor != null) {   
    136.                 g.setColor(shortColor);   
    137.                 g.fillRect(x, rect.y, w, rect.height);   
    138.             }   
    139.         }   
    140.   
    141.         rect = getVDropLineRect(loc);   
    142.         if (rect != null) {   
    143.             int y = rect.y;   
    144.             int h = rect.height;   
    145.             if (color != null) {   
    146.                 extendRect(rect, false);   
    147.                 g.setColor(color);   
    148.                 g.fillRect(rect.x, rect.y, rect.width, rect.height);   
    149.             }   
    150.             if (!loc.isInsertRow() && shortColor != null) {   
    151.                 g.setColor(shortColor);   
    152.                 g.fillRect(rect.x, y, rect.width, h);   
    153.             }   
    154.         }   
    155.     }   
    156.        
    157.     /*  
    158.      * Paints the grid lines within <I>aRect</I>, using the grid  
    159.      * color set with <I>setGridColor</I>. Paints vertical lines  
    160.      * if <code>getShowVerticalLines()</code> returns true and paints  
    161.      * horizontal lines if <code>getShowHorizontalLines()</code>  
    162.      * returns true.  
    163.      */  
    164.     private void paintGrid(Graphics g, int rMin, int rMax, int cMin, int cMax) {   
    165.         g.setColor(table.getGridColor());   
    166.   
    167.         Rectangle minCell = table.getCellRect(rMin, cMin, true);   
    168.         Rectangle maxCell = table.getCellRect(rMax, cMax, true);   
    169.         Rectangle damagedArea = minCell.union( maxCell );   
    170.   
    171.         if (table.getShowHorizontalLines()) {   
    172.             int tableWidth = damagedArea.x + damagedArea.width;   
    173.             int y = damagedArea.y;   
    174.             for (int row = rMin; row <= rMax; row++) {   
    175.                 y += table.getRowHeight(row);   
    176.                 g.drawLine(damagedArea.x, y - 1, tableWidth - 1, y - 1);   
    177.             }   
    178.         }   
    179.         if (table.getShowVerticalLines()) {   
    180.             TableColumnModel cm = table.getColumnModel();   
    181.             int tableHeight = damagedArea.y + damagedArea.height;   
    182.             int x;   
    183.             if (table.getComponentOrientation().isLeftToRight()) {   
    184.                 x = damagedArea.x;   
    185.                 for (int column = cMin; column <= cMax; column++) {   
    186.                     int w = cm.getColumn(column).getWidth();   
    187.                     x += w;   
    188.                     g.drawLine(x - 10, x - 1, tableHeight - 1);   
    189.                 }   
    190.             } else {   
    191.                 x = damagedArea.x;   
    192.                 for (int column = cMax; column >= cMin; column--) {   
    193.                     int w = cm.getColumn(column).getWidth();   
    194.                     x += w;   
    195.                     g.drawLine(x - 10, x - 1, tableHeight - 1);   
    196.                 }   
    197.             }   
    198.         }   
    199.     }   
    200.        
    201.     private void paintCells(Graphics g, int rMin, int rMax, int cMin, int cMax) {   
    202.         JTableHeader header = table.getTableHeader();   
    203.         TableColumn draggedColumn = (header == null) ? null : header.getDraggedColumn();   
    204.   
    205.         TableColumnModel cm = table.getColumnModel();   
    206.         int columnMargin = cm.getColumnMargin();   
    207.             Rectangle cellRect;   
    208.         TableColumn aColumn;   
    209.         int columnWidth;   
    210.         if (table.getComponentOrientation().isLeftToRight()) {   
    211.             for(int row = rMin; row <= rMax; row++) {   
    212.                 if( table instanceof GridBagTable )   
    213.                     cellRect = ((GridBagTable)table).getGridCellRect(row, cMin, false);   
    214.                 else  
    215.                     cellRect = table.getCellRect(row, cMin, false);   
    216.                 for(int column = cMin; column <= cMax; column++) {   
    217.                     aColumn = cm.getColumn(column);   
    218.                     columnWidth = aColumn.getWidth();                                    
    219.                     //TODO   
    220.                     cellRect.width = columnWidth - columnMargin;   
    221.                     int oldHeight = cellRect.height;   
    222.                     if( table instanceof GridBagTable ){   
    223.                         if(((GridBagTable)table).getGridBagModel().getCellState( row, column) == GridBagModel.COVERED ) {   
    224.                             cellRect.width = 0;   
    225.                             cellRect.height = 0;   
    226.                         }   
    227.                         else{   
    228.                             int h = ((GridBagTable)table).getGridBagModel().getColumnGrid(row, column);   
    229.                             if( h >1 ){   
    230.                                 forint n=1; n<h; n++)   
    231.                                     cellRect.width += cm.getColumn(column+n).getWidth();   
    232.                             }   
    233.                             int v = ((GridBagTable)table).getGridBagModel().getRowGrid(row, column);   
    234.                             if( v >1 ){   
    235.                                 forint n=1; n<v; n++)   
    236.                                     cellRect.height += table.getRowHeight(row+n);   
    237.                             }   
    238.                         }              
    239.                     }                                                                          
    240.                     if (aColumn != draggedColumn) {   
    241.                         paintCell(g, cellRect, row, column);   
    242.                     }                          
    243.                     cellRect.height = oldHeight;                       
    244.                     cellRect.x += columnWidth;   
    245.                 }   
    246.             }   
    247.         } else {   
    248.             for(int row = rMin; row <= rMax; row++) {   
    249.                     cellRect = table.getCellRect(row, cMin, false);   
    250.                     aColumn = cm.getColumn(cMin);   
    251.                     if (aColumn != draggedColumn) {   
    252.                         columnWidth = aColumn.getWidth();   
    253.                         cellRect.width = columnWidth - columnMargin;   
    254.                         paintCell(g, cellRect, row, cMin);   
    255.                     }   
    256.                     for(int column = cMin+1; column <= cMax; column++) {   
    257.                         aColumn = cm.getColumn(column);   
    258.                         columnWidth = aColumn.getWidth();   
    259. //                      TODO   
    260.                         cellRect.width = columnWidth - columnMargin;   
    261.                         cellRect.x -= columnWidth;   
    262.                         if (aColumn != draggedColumn) {   
    263.                             paintCell(g, cellRect, row, column);   
    264.                         }   
    265.                 }   
    266.             }   
    267.         }   
    268.   
    269.             // Paint the dragged column if we are dragging.   
    270.             if (draggedColumn != null) {   
    271.             paintDraggedArea(g, rMin, rMax, draggedColumn, header.getDraggedDistance());   
    272.         }   
    273.   
    274.         // Remove any renderers that may be left in the rendererPane.   
    275.         rendererPane.removeAll();   
    276.         }   
    277.        
    278.     private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {   
    279.         if (table.isEditing() && table.getEditingRow()==row &&   
    280.                                  table.getEditingColumn()==column) {   
    281.             Component component = table.getEditorComponent();   
    282.         component.setBounds(cellRect);   
    283.             component.validate();   
    284.         }   
    285.         else {   
    286.             TableCellRenderer renderer = table.getCellRenderer(row, column);   
    287.             Component component = table.prepareRenderer(renderer, row, column);   
    288.                
    289.             if( component instanceof JComponent ){   
    290.                 ((JComponent)component).setBorder(BorderFactory.createLineBorder(Color.gray));   
    291.             }   
    292.             rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,   
    293.                                         cellRect.width, cellRect.height, true);              
    294.         }   
    295.     }   
    296.        
    297.     private Rectangle getHDropLineRect(JTable.DropLocation loc) {   
    298.         if (!loc.isInsertRow()) {   
    299.             return null;   
    300.         }   
    301.   
    302.         int row = loc.getRow();   
    303.         int col = loc.getColumn();   
    304.         if (col >= table.getColumnCount()) {   
    305.             col--;   
    306.         }   
    307.   
    308.         Rectangle rect = table.getCellRect(row, col, true);   
    309.   
    310.         if (row >= table.getRowCount()) {   
    311.             row--;   
    312.             Rectangle prevRect = table.getCellRect(row, col, true);   
    313.             rect.y = prevRect.y + prevRect.height;   
    314.         }   
    315.   
    316.         if (rect.y == 0) {   
    317.             rect.y = -1;   
    318.         } else {   
    319.             rect.y -= 2;   
    320.         }   
    321.   
    322.         rect.height = 3;   
    323.   
    324.         return rect;   
    325.     }   
    326.        
    327.     private void paintDraggedArea(Graphics g, int rMin, int rMax, TableColumn draggedColumn, int distance) {   
    328.         int draggedColumnIndex = viewIndexForColumn(draggedColumn);   
    329.   
    330.         Rectangle minCell = table.getCellRect(rMin, draggedColumnIndex, true);   
    331.     Rectangle maxCell = table.getCellRect(rMax, draggedColumnIndex, true);   
    332.   
    333.     Rectangle vacatedColumnRect = minCell.union(maxCell);   
    334.   
    335.     // Paint a gray well in place of the moving column.   
    336.     g.setColor(table.getParent().getBackground());   
    337.     g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,   
    338.            vacatedColumnRect.width, vacatedColumnRect.height);   
    339.   
    340.     // Move to the where the cell has been dragged.   
    341.     vacatedColumnRect.x += distance;   
    342.   
    343.     // Fill the background.   
    344.     g.setColor(table.getBackground());   
    345.     g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,   
    346.            vacatedColumnRect.width, vacatedColumnRect.height);   
    347.   
    348.     // Paint the vertical grid lines if necessary.   
    349.     if (table.getShowVerticalLines()) {   
    350.         g.setColor(table.getGridColor());   
    351.         int x1 = vacatedColumnRect.x;   
    352.         int y1 = vacatedColumnRect.y;   
    353.         int x2 = x1 + vacatedColumnRect.width - 1;   
    354.         int y2 = y1 + vacatedColumnRect.height - 1;   
    355.         // Left   
    356.         g.drawLine(x1-1, y1, x1-1, y2);   
    357.         // Right   
    358.         g.drawLine(x2, y1, x2, y2);   
    359.     }   
    360.   
    361.     for(int row = rMin; row <= rMax; row++) {   
    362.         // Render the cell value   
    363.         Rectangle r = table.getCellRect(row, draggedColumnIndex, false);   
    364.         r.x += distance;   
    365.         paintCell(g, r, row, draggedColumnIndex);   
    366.   
    367.         // Paint the (lower) horizontal grid line if necessary.   
    368.         if (table.getShowHorizontalLines()) {   
    369.         g.setColor(table.getGridColor());   
    370.         Rectangle rcr = table.getCellRect(row, draggedColumnIndex, true);   
    371.         rcr.x += distance;   
    372.         int x1 = rcr.x;   
    373.         int y1 = rcr.y;   
    374.         int x2 = x1 + rcr.width - 1;   
    375.         int y2 = y1 + rcr.height - 1;   
    376.         g.drawLine(x1, y2, x2, y2);   
    377.         }   
    378.     }   
    379.     }   
    380.        
    381.     private int viewIndexForColumn(TableColumn aColumn) {   
    382.         TableColumnModel cm = table.getColumnModel();   
    383.         for (int column = 0; column < cm.getColumnCount(); column++) {   
    384.             if (cm.getColumn(column) == aColumn) {   
    385.                 return column;   
    386.             }   
    387.         }   
    388.         return -1;   
    389.     }   
    390.        
    391.     private Rectangle extendRect(Rectangle rect, boolean horizontal) {   
    392.         if (rect == null) {   
    393.             return rect;   
    394.         }   
    395.   
    396.         if (horizontal) {   
    397.             rect.x = 0;   
    398.             rect.width = table.getWidth();   
    399.         } else {   
    400.             rect.y = 0;   
    401.   
    402.             if (table.getRowCount() != 0) {   
    403.                 Rectangle lastRect = table.getCellRect(table.getRowCount() - 10true);   
    404.                 rect.height = lastRect.y + lastRect.height;   
    405.             } else {   
    406.                 rect.height = table.getHeight();   
    407.             }   
    408.         }   
    409.   
    410.         return rect;   
    411.     }   
    412.        
    413.     private Rectangle getVDropLineRect(JTable.DropLocation loc) {   
    414.         if (!loc.isInsertColumn()) {   
    415.             return null;   
    416.         }   
    417.   
    418.         boolean ltr = table.getComponentOrientation().isLeftToRight();   
    419.         int col = loc.getColumn();   
    420.         Rectangle rect = table.getCellRect(loc.getRow(), col, true);   
    421.   
    422.         if (col >= table.getColumnCount()) {   
    423.             col--;   
    424.             rect = table.getCellRect(loc.getRow(), col, true);   
    425.             if (ltr) {   
    426.                 rect.x = rect.x + rect.width;   
    427.             }   
    428.         } else if (!ltr) {   
    429.             rect.x = rect.x + rect.width;   
    430.         }   
    431.   
    432.         if (rect.x == 0) {   
    433.             rect.x = -1;   
    434.         } else {   
    435.             rect.x -= 2;   
    436.         }   
    437.            
    438.         rect.width = 3;   
    439.   
    440.         return rect;   
    441.     }   
    442.   
    443. }  // End of Class BasicTableUI  
    package org.dxj.guitools.gridbagtable;
    import java.awt.Color;
    import java.awt.Component;
    import java.awt.Dimension;
    import java.awt.Graphics;
    import java.awt.Point;
    import java.awt.Rectangle;
    import java.util.Enumeration;
    import javax.swing.BorderFactory;
    import javax.swing.JComponent;
    import javax.swing.JTable;
    import javax.swing.UIManager;
    import javax.swing.plaf.basic.BasicTableUI;
    import javax.swing.table.JTableHeader;
    import javax.swing.table.TableCellRenderer;
    import javax.swing.table.TableColumn;
    import javax.swing.table.TableColumnModel;
    public class GridBagTableUI extends BasicTableUI
    {
    public Dimension getPreferredSize(JComponent c) {
    long width = 0;
    Enumeration<TableColumn> enumeration = table.getColumnModel().getColumns();
    while (enumeration.hasMoreElements()) {
    TableColumn aColumn = (TableColumn)enumeration.nextElement();
    width = width + aColumn.getPreferredWidth();
    }
    return createTableSize(width);
    }
    private Dimension createTableSize(long width) {
    int height = 0;
    int rowCount = table.getRowCount();
    if (rowCount > 0 && table.getColumnCount() > 0) {
    Rectangle r = table.getCellRect(rowCount-1, 0, true);
    height = r.y + r.height;
    }
    // Width is always positive. The call to abs() is a workaround for
    // a bug in the 1.1.6 JIT on Windows.
    long tmp = Math.abs(width);
    if (tmp > Integer.MAX_VALUE) {
    tmp = Integer.MAX_VALUE;
    }
    return new Dimension((int)tmp, height);
    }
    public void paint(Graphics g, JComponent c) {
    Rectangle clip = g.getClipBounds();
    Rectangle bounds = table.getBounds();
    // account for the fact that the graphics has already been translated
    // into the table's bounds
    bounds.x = bounds.y = 0;
    if (table.getRowCount() <= 0 || table.getColumnCount() <= 0 ||
    // this check prevents us from painting the entire table
    // when the clip doesn't intersect our bounds at all
    !bounds.intersects(clip)) {
    paintDropLines(g);
    return;
    }
    boolean ltr = table.getComponentOrientation().isLeftToRight();
    Point upperLeft = clip.getLocation();
    if (!ltr) {
    upperLeft.x++;
    }
    Point lowerRight = new Point(clip.x + clip.width - (ltr ? 1 : 0),
    clip.y + clip.height);
    int rMin = table.rowAtPoint(upperLeft);
    int rMax = table.rowAtPoint(lowerRight);
    // This should never happen (as long as our bounds intersect the clip,
    // which is why we bail above if that is the case).
    if (rMin == -1) {
    rMin = 0;
    }
    // If the table does not have enough rows to fill the view we'll get -1.
    // (We could also get -1 if our bounds don't intersect the clip,
    // which is why we bail above if that is the case).
    // Replace this with the index of the last row.
    if (rMax == -1) {
    rMax = table.getRowCount()-1;
    }
    int cMin = table.columnAtPoint(ltr ? upperLeft : lowerRight);
    int cMax = table.columnAtPoint(ltr ? lowerRight : upperLeft);
    // This should never happen.
    if (cMin == -1) {
    cMin = 0;
    }
    // If the table does not have enough columns to fill the view we'll get -1.
    // Replace this with the index of the last column.
    if (cMax == -1) {
    cMax = table.getColumnCount()-1;
    }
    // Paint the grid.
    //paintGrid(g, rMin, rMax, cMin, cMax);
    // Paint the cells.
    paintCells(g, rMin, rMax, cMin, cMax);
    paintDropLines(g);
    }
    private void paintDropLines(Graphics g) {
    JTable.DropLocation loc = table.getDropLocation();
    if (loc == null) {
    return;
    }
    Color color = UIManager.getColor("Table.dropLineColor");
    Color shortColor = UIManager.getColor("Table.dropLineShortColor");
    if (color == null && shortColor == null) {
    return;
    }
    Rectangle rect;
    rect = getHDropLineRect(loc);
    if (rect != null) {
    int x = rect.x;
    int w = rect.width;
    if (color != null) {
    extendRect(rect, true);
    g.setColor(color);
    g.fillRect(rect.x, rect.y, rect.width, rect.height);
    }
    if (!loc.isInsertColumn() && shortColor != null) {
    g.setColor(shortColor);
    g.fillRect(x, rect.y, w, rect.height);
    }
    }
    rect = getVDropLineRect(loc);
    if (rect != null) {
    int y = rect.y;
    int h = rect.height;
    if (color != null) {
    extendRect(rect, false);
    g.setColor(color);
    g.fillRect(rect.x, rect.y, rect.width, rect.height);
    }
    if (!loc.isInsertRow() && shortColor != null) {
    g.setColor(shortColor);
    g.fillRect(rect.x, y, rect.width, h);
    }
    }
    }
    /*
    * Paints the grid lines within <I>aRect</I>, using the grid
    * color set with <I>setGridColor</I>. Paints vertical lines
    * if <code>getShowVerticalLines()</code> returns true and paints
    * horizontal lines if <code>getShowHorizontalLines()</code>
    * returns true.
    */
    private void paintGrid(Graphics g, int rMin, int rMax, int cMin, int cMax) {
    g.setColor(table.getGridColor());
    Rectangle minCell = table.getCellRect(rMin, cMin, true);
    Rectangle maxCell = table.getCellRect(rMax, cMax, true);
    Rectangle damagedArea = minCell.union( maxCell );
    if (table.getShowHorizontalLines()) {
    int tableWidth = damagedArea.x + damagedArea.width;
    int y = damagedArea.y;
    for (int row = rMin; row <= rMax; row++) {
    y += table.getRowHeight(row);
    g.drawLine(damagedArea.x, y - 1, tableWidth - 1, y - 1);
    }
    }
    if (table.getShowVerticalLines()) {
    TableColumnModel cm = table.getColumnModel();
    int tableHeight = damagedArea.y + damagedArea.height;
    int x;
    if (table.getComponentOrientation().isLeftToRight()) {
    x = damagedArea.x;
    for (int column = cMin; column <= cMax; column++) {
    int w = cm.getColumn(column).getWidth();
    x += w;
    g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
    }
    } else {
    x = damagedArea.x;
    for (int column = cMax; column >= cMin; column--) {
    int w = cm.getColumn(column).getWidth();
    x += w;
    g.drawLine(x - 1, 0, x - 1, tableHeight - 1);
    }
    }
    }
    }
    private void paintCells(Graphics g, int rMin, int rMax, int cMin, int cMax) {
    JTableHeader header = table.getTableHeader();
    TableColumn draggedColumn = (header == null) ? null : header.getDraggedColumn();
    TableColumnModel cm = table.getColumnModel();
    int columnMargin = cm.getColumnMargin();
    Rectangle cellRect;
    TableColumn aColumn;
    int columnWidth;
    if (table.getComponentOrientation().isLeftToRight()) {
    for(int row = rMin; row <= rMax; row++) {
    if( table instanceof GridBagTable )
    cellRect = ((GridBagTable)table).getGridCellRect(row, cMin, false);
    else
    cellRect = table.getCellRect(row, cMin, false);
    for(int column = cMin; column <= cMax; column++) {
    aColumn = cm.getColumn(column);
    columnWidth = aColumn.getWidth();
    //TODO
    cellRect.width = columnWidth - columnMargin;
    int oldHeight = cellRect.height;
    if( table instanceof GridBagTable ){
    if(((GridBagTable)table).getGridBagModel().getCellState( row, column) == GridBagModel.COVERED ) {
    cellRect.width = 0;
    cellRect.height = 0;
    }
    else{
    int h = ((GridBagTable)table).getGridBagModel().getColumnGrid(row, column);
    if( h >1 ){
    for( int n=1; n<h; n++)
    cellRect.width += cm.getColumn(column+n).getWidth();
    }
    int v = ((GridBagTable)table).getGridBagModel().getRowGrid(row, column);
    if( v >1 ){
    for( int n=1; n<v; n++)
    cellRect.height += table.getRowHeight(row+n);
    }
    }
    }
    if (aColumn != draggedColumn) {
    paintCell(g, cellRect, row, column);
    }
    cellRect.height = oldHeight;
    cellRect.x += columnWidth;
    }
    }
    } else {
    for(int row = rMin; row <= rMax; row++) {
    cellRect = table.getCellRect(row, cMin, false);
    aColumn = cm.getColumn(cMin);
    if (aColumn != draggedColumn) {
    columnWidth = aColumn.getWidth();
    cellRect.width = columnWidth - columnMargin;
    paintCell(g, cellRect, row, cMin);
    }
    for(int column = cMin+1; column <= cMax; column++) {
    aColumn = cm.getColumn(column);
    columnWidth = aColumn.getWidth();
    //
    TODO
    cellRect.width = columnWidth - columnMargin;
    cellRect.x -= columnWidth;
    if (aColumn != draggedColumn) {
    paintCell(g, cellRect, row, column);
    }
    }
    }
    }
    // Paint the dragged column if we are dragging.
    if (draggedColumn != null) {
    paintDraggedArea(g, rMin, rMax, draggedColumn, header.getDraggedDistance());
    }
    // Remove any renderers that may be left in the rendererPane.
    rendererPane.removeAll();
    }
    private void paintCell(Graphics g, Rectangle cellRect, int row, int column) {
    if (table.isEditing() && table.getEditingRow()==row &&
    table.getEditingColumn()==column) {
    Component component = table.getEditorComponent();
    component.setBounds(cellRect);
    component.validate();
    }
    else {
    TableCellRenderer renderer = table.getCellRenderer(row, column);
    Component component = table.prepareRenderer(renderer, row, column);
    if( component instanceof JComponent ){
    ((JComponent)component).setBorder(BorderFactory.createLineBorder(Color.gray));
    }
    rendererPane.paintComponent(g, component, table, cellRect.x, cellRect.y,
    cellRect.width, cellRect.height, true);
    }
    }
    private Rectangle getHDropLineRect(JTable.DropLocation loc) {
    if (!loc.isInsertRow()) {
    return null;
    }
    int row = loc.getRow();
    int col = loc.getColumn();
    if (col >= table.getColumnCount()) {
    col--;
    }
    Rectangle rect = table.getCellRect(row, col, true);
    if (row >= table.getRowCount()) {
    row--;
    Rectangle prevRect = table.getCellRect(row, col, true);
    rect.y = prevRect.y + prevRect.height;
    }
    if (rect.y == 0) {
    rect.y = -1;
    } else {
    rect.y -= 2;
    }
    rect.height = 3;
    return rect;
    }
    private void paintDraggedArea(Graphics g, int rMin, int rMax, TableColumn draggedColumn, int distance) {
    int draggedColumnIndex = viewIndexForColumn(draggedColumn);
    Rectangle minCell = table.getCellRect(rMin, draggedColumnIndex, true);
    Rectangle maxCell = table.getCellRect(rMax, draggedColumnIndex, true);
    Rectangle vacatedColumnRect = minCell.union(maxCell);
    // Paint a gray well in place of the moving column.
    g.setColor(table.getParent().getBackground());
    g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
    vacatedColumnRect.width, vacatedColumnRect.height);
    // Move to the where the cell has been dragged.
    vacatedColumnRect.x += distance;
    // Fill the background.
    g.setColor(table.getBackground());
    g.fillRect(vacatedColumnRect.x, vacatedColumnRect.y,
    vacatedColumnRect.width, vacatedColumnRect.height);
    // Paint the vertical grid lines if necessary.
    if (table.getShowVerticalLines()) {
    g.setColor(table.getGridColor());
    int x1 = vacatedColumnRect.x;
    int y1 = vacatedColumnRect.y;
    int x2 = x1 + vacatedColumnRect.width - 1;
    int y2 = y1 + vacatedColumnRect.height - 1;
    // Left
    g.drawLine(x1-1, y1, x1-1, y2);
    // Right
    g.drawLine(x2, y1, x2, y2);
    }
    for(int row = rMin; row <= rMax; row++) {
    // Render the cell value
    Rectangle r = table.getCellRect(row, draggedColumnIndex, false);
    r.x += distance;
    paintCell(g, r, row, draggedColumnIndex);
    // Paint the (lower) horizontal grid line if necessary.
    if (table.getShowHorizontalLines()) {
    g.setColor(table.getGridColor());
    Rectangle rcr = table.getCellRect(row, draggedColumnIndex, true);
    rcr.x += distance;
    int x1 = rcr.x;
    int y1 = rcr.y;
    int x2 = x1 + rcr.width - 1;
    int y2 = y1 + rcr.height - 1;
    g.drawLine(x1, y2, x2, y2);
    }
    }
    }
    private int viewIndexForColumn(TableColumn aColumn) {
    TableColumnModel cm = table.getColumnModel();
    for (int column = 0; column < cm.getColumnCount(); column++) {
    if (cm.getColumn(column) == aColumn) {
    return column;
    }
    }
    return -1;
    }
    private Rectangle extendRect(Rectangle rect, boolean horizontal) {
    if (rect == null) {
    return rect;
    }
    if (horizontal) {
    rect.x = 0;
    rect.width = table.getWidth();
    } else {
    rect.y = 0;
    if (table.getRowCount() != 0) {
    Rectangle lastRect = table.getCellRect(table.getRowCount() - 1, 0, true);
    rect.height = lastRect.y + lastRect.height;
    } else {
    rect.height = table.getHeight();
    }
    }
    return rect;
    }
    private Rectangle getVDropLineRect(JTable.DropLocation loc) {
    if (!loc.isInsertColumn()) {
    return null;
    }
    boolean ltr = table.getComponentOrientation().isLeftToRight();
    int col = loc.getColumn();
    Rectangle rect = table.getCellRect(loc.getRow(), col, true);
    if (col >= table.getColumnCount()) {
    col--;
    rect = table.getCellRect(loc.getRow(), col, true);
    if (ltr) {
    rect.x = rect.x + rect.width;
    }
    } else if (!ltr) {
    rect.x = rect.x + rect.width;
    }
    if (rect.x == 0) {
    rect.x = -1;
    } else {
    rect.x -= 2;
    }
    rect.width = 3;
    return rect;
    }
    }
    // End of Class BasicTableUI
    

      测试代码:

    Java代码 复制代码  收藏代码
    1. import java.awt.BorderLayout;   
    2. import java.awt.event.ActionEvent;   
    3. import java.awt.event.ActionListener;   
    4.   
    5. import javax.swing.JButton;   
    6. import javax.swing.JFrame;   
    7. import javax.swing.JScrollPane;   
    8. import javax.swing.table.DefaultTableModel;   
    9.   
    10. import com.jrf.jgrid.guitools.gridbagtable.GridBagTable;   
    11.   
    12.   
    13. public class Test implements ActionListener{   
    14.        
    15.     GridBagTable table;   
    16.     public Test()   
    17.     {   
    18.         JFrame d = new JFrame();   
    19.         DefaultTableModel model = new DefaultTableModel(5,5);   
    20.            
    21.         table = new GridBagTable(model);   
    22.         table.setRowHeight(20);   
    23.            
    24.         JScrollPane pane = new JScrollPane(table);   
    25.         d.getContentPane().add(pane, BorderLayout.CENTER);   
    26.         JButton btn = new JButton("合并/拆分");   
    27.         d.getContentPane().add(btn, BorderLayout.NORTH);   
    28.         btn.addActionListener(this);   
    29.         d.setBounds(00400400);   
    30.         d.setVisible(true);   
    31.     }   
    32.        
    33.     public static void main(String[] fsd){   
    34.         new Test();   
    35.     }   
    36.        
    37.     public void actionPerformed(ActionEvent e) {   
    38.         table.mergeCells(table.getSelectedRows(), table.getSelectedColumns());   
    39.     }   
    40. }  

最后

以上就是隐形冬天为你收集整理的Java Swing写的支持合并单元格的JTable的全部内容,希望文章能够帮你解决Java Swing写的支持合并单元格的JTable所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部