Java Swing写的支持合并单元格的JTable
来源:互联网 发布:视频美容软件 编辑:程序博客网 时间:2024/06/05 23:05
年前在网上参加了一个JavaSwing的招聘上机考试。招聘方要求开发一个类似EXCEL支持单元格合并的JTable。差不多用了5天的时间提交代码,最后被告知测试通过,我提出是否可做兼职,对方回复需要到上海做全职开发,最后也就放弃了。最近公司的一个项目中需要用到以前的代码,偶又重构了一次,设计思想来源于ListSelectionModel。
GridBagModel:抽象模型接口。该接口用于描述表格中单元格的合并状态。
DefaultGridBagTableModel:GridBagModel的默认实现。
GridBagTable:继承自JTable的控制器。通过该类中的方法控制表格单元的合并和拆分。
GridBagTableUI:GridBagTable对应的UI。
TODO:(已合并)行、列的插入,删除操作对应的GridBagModel的修改,不过已留接口。
- 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);
- }
- }
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); }}
- 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();
- }
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();}
- 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();
- }
- }
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>>();elsegridInfo.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);}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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();}@Overridepublic 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;}@Overridepublic 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}@Overridepublic 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]);}@Overridepublic 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;elsesetGrid(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();}}
- 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
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
测试代码:
- import java.awt.BorderLayout;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JScrollPane;
- import javax.swing.table.DefaultTableModel;
- import com.jrf.jgrid.guitools.gridbagtable.GridBagTable;
- public class Test implements ActionListener{
- GridBagTable table;
- public Test()
- {
- JFrame d = new JFrame();
- DefaultTableModel model = new DefaultTableModel(5,5);
- table = new GridBagTable(model);
- table.setRowHeight(20);
- JScrollPane pane = new JScrollPane(table);
- d.getContentPane().add(pane, BorderLayout.CENTER);
- JButton btn = new JButton("合并/拆分");
- d.getContentPane().add(btn, BorderLayout.NORTH);
- btn.addActionListener(this);
- d.setBounds(0, 0, 400, 400);
- d.setVisible(true);
- }
- public static void main(String[] fsd){
- new Test();
- }
- public void actionPerformed(ActionEvent e) {
- table.mergeCells(table.getSelectedRows(), table.getSelectedColumns());
- }
- } 年前在网上参加了一个JavaSwing的招聘上机考试。招聘方要求开发一个类似EXCEL支持单元格合并的JTable。差不多用了5天的时间提交代码,最后被告知测试通过,我提出是否可做兼职,对方回复需要到上海做全职开发,最后也就放弃了。最近公司的一个项目中需要用到以前的代码,偶又重构了一次,设计思想来源于ListSelectionModel。
GridBagModel:抽象模型接口。该接口用于描述表格中单元格的合并状态。
DefaultGridBagTableModel:GridBagModel的默认实现。
GridBagTable:继承自JTable的控制器。通过该类中的方法控制表格单元的合并和拆分。
GridBagTableUI:GridBagTable对应的UI。
TODO:(已合并)行、列的插入,删除操作对应的GridBagModel的修改,不过已留接口。- 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);
- }
- }
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); }}
- 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();
- }
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();}
- 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();
- }
- }
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>>();elsegridInfo.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);}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic 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();}@Overridepublic 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;}@Overridepublic 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}@Overridepublic 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]);}@Overridepublic 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;elsesetGrid(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();}}
- 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
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
测试代码:
- import java.awt.BorderLayout;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JScrollPane;
- import javax.swing.table.DefaultTableModel;
- import com.jrf.jgrid.guitools.gridbagtable.GridBagTable;
- public class Test implements ActionListener{
- GridBagTable table;
- public Test()
- {
- JFrame d = new JFrame();
- DefaultTableModel model = new DefaultTableModel(5,5);
- table = new GridBagTable(model);
- table.setRowHeight(20);
- JScrollPane pane = new JScrollPane(table);
- d.getContentPane().add(pane, BorderLayout.CENTER);
- JButton btn = new JButton("合并/拆分");
- d.getContentPane().add(btn, BorderLayout.NORTH);
- btn.addActionListener(this);
- d.setBounds(0, 0, 400, 400);
- d.setVisible(true);
- }
- public static void main(String[] fsd){
- new Test();
- }
- public void actionPerformed(ActionEvent e) {
- table.mergeCells(table.getSelectedRows(), table.getSelectedColumns());
- }
- }
- Java Swing写的支持合并单元格的JTable
- Jtable单元格合并的问题
- Java Swing-JTable中的单元格拆分与合并
- java swing jtable 给指定的(一个或多个)单元格设置背景色
- Java Swing JTable 表格【12:为表格的单元格指定文字说明】
- SWING学习:JTable实现自定义的编辑单元格 (1)
- SWING学习:JTable实现自定义的编辑单元格 (2)
- 再议将Swing组件与JTable的单元格组件
- JAVA获取Jtable的单元格中的值
- Java Swing中JTable的使用
- Java Swing中JTable的使用
- java swing jtable的使用(一)
- java swing 隐藏jtable 列的方法
- Java swing JTable的简单界面
- java Swing JTable的复杂应用实例
- java swing 隐藏jtable 列的方法
- Java Swing中JTable的使用
- swing jTable 自定义单元格
- Symbian DBMS 读取EDbColLongText (长字段读取)
- js判断字符长度
- js日期作差(相差几天)
- js增加(删除)行
- 麻省理工的职场行为心理
- Java Swing写的支持合并单元格的JTable
- myEclipse8.5添加反编译插件
- 做个向日葵族
- 工作总结
- Oracle-分析函数-over函数
- Oracle-分组函数
- java.lang.NoClassDefFoundError: org/jboss/logmanager/Logger$AttachmentKey 的一个解决办法
- D触发器的二分频电路
- 配置数据库的归档模式(Configure the database archive Model)