年前在网上参加了一个JavaSwing的招聘上机考试。招聘方要求开发一个类似EXCEL支持单元格合并的JTable。差不多用了5天的时间提交代码,最后被告知测试通过,我提出是否可做兼职,对方回复需要到上海做全职开发,最后也就放弃了。最近公司的一个项目中需要用到以前的代码,偶又重构了一次,设计思想来源于ListSelectionModel。
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; 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.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
GridBagModel:抽象模型接口。该接口用于描述表格中单元格的合并状态。
DefaultGridBagTableModel:GridBagModel的默认实现。
GridBagTable:继承自JTable的控制器。通过该类中的方法控制表格单元的合并和拆分。
GridBagTableUI:GridBagTable对应的UI。
TODO:(已合并)行、列的插入,删除操作对应的GridBagModel的修改,不过已留接口。
- packageorg.dxj.guitools.gridbagtable;
- importjava.awt.Component;
- importjava.awt.Point;
- importjava.awt.Rectangle;
- importjava.util.Enumeration;
- importjava.util.EventObject;
- importjavax.swing.DefaultCellEditor;
- importjavax.swing.JTable;
- importjavax.swing.SwingUtilities;
- importjavax.swing.event.TableModelEvent;
- importjavax.swing.table.AbstractTableModel;
- importjavax.swing.table.TableColumn;
- importjavax.swing.table.TableColumnModel;
- /**
- *@author15860102@qq.com
- */
- publicclassGridBagTableextendsJTable{
- GridBagModelgridBagModel;
- publicGridBagModelgetGridBagModel(){
- returngridBagModel;
- }
- publicvoidsetGridBagModel(GridBagModelgridBagModel){
- if(gridBagModel!=null&&gridBagModel!=this.gridBagModel)
- this.gridBagModel=gridBagModel;
- }
- publicGridBagTable(AbstractTableModeldm){
- super(dm);
- getTableHeader().setReorderingAllowed(false);
- gridBagModel=newDefaultGridBagTableModel(dm);
- getColumnModel().setColumnSelectionAllowed(true);
- }
- privatevoidupdateSubComponentUI(ObjectcomponentShell){
- if(componentShell==null){
- return;
- }
- Componentcomponent=null;
- if(componentShellinstanceofComponent){
- component=(Component)componentShell;
- }
- if(componentShellinstanceofDefaultCellEditor){
- component=((DefaultCellEditor)componentShell).getComponent();
- }
- if(component!=null){
- SwingUtilities.updateComponentTreeUI(component);
- }
- }
- publicvoidupdateUI(){
- //UpdatetheUIsofthecellrenderers,celleditorsandheaderrenderers.
- TableColumnModelcm=getColumnModel();
- for(intcolumn=0;column<cm.getColumnCount();column++){
- TableColumnaColumn=cm.getColumn(column);
- updateSubComponentUI(aColumn.getCellRenderer());
- updateSubComponentUI(aColumn.getCellEditor());
- updateSubComponentUI(aColumn.getHeaderRenderer());
- }
- //UpdatetheUIsofallthedefaultrenderers.
- EnumerationdefaultRenderers=defaultRenderersByColumnClass.elements();
- while(defaultRenderers.hasMoreElements()){
- updateSubComponentUI(defaultRenderers.nextElement());
- }
- //UpdatetheUIsofallthedefaulteditors.
- EnumerationdefaultEditors=defaultEditorsByColumnClass.elements();
- while(defaultEditors.hasMoreElements()){
- updateSubComponentUI(defaultEditors.nextElement());
- }
- //UpdatetheUIofthetableheader
- if(tableHeader!=null&&tableHeader.getParent()==null){
- tableHeader.updateUI();
- }
- setUI(newGridBagTableUI());
- }
- publicRectanglegetGridCellRect(introw,intcolumn,booleanincludeSpacing){
- returnsuper.getCellRect(row,column,includeSpacing);
- }
- publicRectanglegetCellRect(introw,intcolumn,booleanincludeSpacing){
- RectanglecellRect=super.getCellRect(row,column,includeSpacing);
- intcols=gridBagModel.getColumnGrid(row,column);
- TableColumnModelcm=getColumnModel();
- for(intn=1;n<cols;n++)
- cellRect.width+=cm.getColumn(column+n).getWidth();
- introws=gridBagModel.getRowGrid(row,column);
- for(intn=1;n<rows;n++)
- cellRect.height+=getRowHeight(row+n);
- returncellRect;
- }
- publicvoidtableChanged(TableModelEvente){
- super.tableChanged(e);
- //TODO
- }
- publicbooleanmergeCells(intstartRow,intendRow,intstartColumn,intendColumn){
- if(gridBagModel.mergeCells(startRow,endRow,startColumn,endColumn)){
- repaint();
- returntrue;
- }
- returnfalse;
- }
- publicbooleanmergeCells(int[]rows,int[]columns){
- if(gridBagModel.mergeCells(rows,columns)){
- repaint();
- returntrue;
- }
- returnfalse;
- }
- publicbooleanspliteCellAt(introw,intcolumn){
- if(gridBagModel.spliteCellAt(row,column)){
- repaint();
- returntrue;
- }
- returnfalse;
- }
- publicvoidchangeSelection(introwIndex,intcolumnIndex,booleantoggle,booleanextend){
- if(gridBagModel.getCellState(rowIndex,columnIndex)!=GridBagModel.COVERED)
- super.changeSelection(rowIndex,columnIndex,toggle,extend);
- Pointp;
- for(introw=rowIndex;row>=0;row--){
- for(intcol=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();
- }
- publicbooleaneditCellAt(introwIndex,intcolumnIndex,EventObjecte){
- if(gridBagModel.getCellState(rowIndex,columnIndex)!=GridBagModel.COVERED)
- returnsuper.editCellAt(rowIndex,columnIndex,e);
- Pointp;
- for(introw=rowIndex;row>=0;row--){
- for(intcol=columnIndex;col>=0;col--){
- p=gridBagModel.getGrid(row,col);
- if(col+p.x>columnIndex&&row+p.y>rowIndex){
- rowIndex=row;
- columnIndex=col;
- break;
- }
- }
- }
- returnsuper.editCellAt(rowIndex,columnIndex,e);
- }
- }
- packageorg.dxj.guitools.gridbagtable;
- importjava.awt.Point;
- publicinterfaceGridBagModel{
- //格子处于正常状态
- intDEFAULT=0;
- //格子合并了其他的格子
- intMERGE=1;
- //格子被其他格子合并
- intCOVERED=-1;
- /**
- *@paramrow行
- *@paramcolumn列
- *@return该单元格在行、列的跨度
- */
- PointgetGrid(introw,intcolumn);
- /**
- *在Y轴方向的跨度
- *@paramrow
- *@paramcolumn
- *@return
- */
- intgetRowGrid(introw,intcolumn);
- /**
- *在X轴方向的跨度
- *@paramrow
- *@paramcolumn
- *@return
- */
- intgetColumnGrid(introw,intcolumn);
- /**
- *@paramrows行集合
- *@paramcolumns列集合
- *@return单元格集合是否可以合并在一起
- */
- booleancanMergeCells(int[]rows,int[]columns);
- /**
- *判断该单元格状态
- *@paramrow
- *@paramcolumn
- *@returnMERGE|DEFAULT|COVERED
- */
- intgetCellState(introw,intcolumn);
- /**
- *将单元格集合合并
- *@paramstartRow开始行
- *@paramendRow结束行
- *@paramstartColumn开始列
- *@paramendColumn结束列
- *@return是否合并成功
- */
- booleanmergeCells(intstartRow,intendRow,intstartColumn,intendColumn);
- /**
- *将单元格集合合并
- *@paramrows行集合
- *@paramcolumns列集合
- *@return是否合并成功
- */
- booleanmergeCells(int[]rows,int[]columns);
- /**
- *拆分单元格
- *@paramrow行
- *@paramcolumn列
- *@return是否拆分成功
- */
- booleanspliteCellAt(introw,intcolumn);
- /**
- *清除所有合并
- */
- voidclearMergence();
- }
- packageorg.dxj.guitools.gridbagtable;
- importjava.awt.Point;
- importjava.util.Arrays;
- importjava.util.List;
- importjava.util.Vector;
- importjavax.swing.event.TableModelEvent;
- importjavax.swing.event.TableModelListener;
- importjavax.swing.table.AbstractTableModel;
- publicclassDefaultGridBagTableModelimplementsGridBagModel,TableModelListener{
- protectedAbstractTableModelmodel;
- protectedList<List<Point>>gridInfo;
- DefaultGridBagTableModel(AbstractTableModelmodel){
- gridInfo=newVector<List<Point>>();
- setTableModel(model);
- }
- publicvoidsetTableModel(AbstractTableModelmodel){
- if(model!=null&&model!=this.model){
- if(this.model!=null)
- this.model.removeTableModelListener(this);
- //防止多次添加监听器
- model.removeTableModelListener(this);
- model.addTableModelListener(this);
- this.model=model;
- clearMergence();
- }
- }
- publicvoidclearMergence(){
- if(gridInfo==null)
- gridInfo=newVector<List<Point>>();
- else
- gridInfo.clear();
- if(model==null)
- return;
- //初始化,每个格子占的格子数为(1,1);
- for(introw=model.getRowCount();--row>=0;){
- List<Point>infos=newVector<Point>();
- gridInfo.add(infos);
- for(intcol=model.getColumnCount();--col>=0;){
- infos.add(getDefaultPoint());
- }
- }
- }
- publicPointgetDefaultPoint(){
- returnnewPoint(1,1);
- }
- @Override
- publicbooleancanMergeCells(int[]rows,int[]columns){
- if(rows==null||columns==null)returnfalse;
- Arrays.sort(rows);
- for(intindex=0;index<rows.length-1;index++){
- if(rows[index+1]-rows[index]>1)
- returnfalse;
- }
- Arrays.sort(columns);
- for(intindex=0;index<columns.length-1;index++){
- if(columns[index+1]-columns[index]>1)
- returnfalse;
- }
- returntrue;
- }
- @Override
- publicintgetCellState(introw,intcolumn){
- Pointgrid=getGrid(row,column);
- if(grid==null)returnDEFAULT;
- if(grid.x>1||grid.y>1)
- returnMERGE;
- if(grid.x<=0||grid.y<=0)
- returnCOVERED;
- returnDEFAULT;
- }
- @Override
- publicintgetColumnGrid(introw,intcolumn){
- if(gridInfo!=null&&row>=0&&row<gridInfo.size()){
- List<Point>gridRow=gridInfo.get(row);
- if(gridRow!=null&&column>=0&&column<gridRow.size()){
- Pointpoint=gridRow.get(column);
- if(point!=null)
- returnpoint.x;
- }
- }
- return1;
- }
- @Override
- publicPointgetGrid(introw,intcolumn){
- if(gridInfo!=null&&row>=0&&row<gridInfo.size()){
- List<Point>gridRow=gridInfo.get(row);
- if(gridRow!=null&&column>=0&&column<gridRow.size()){
- returngridRow.get(column);
- }
- }
- returngetDefaultPoint();
- }
- @Override
- publicintgetRowGrid(introw,intcolumn){
- if(gridInfo!=null&&row>=0&&row<gridInfo.size()){
- List<Point>gridRow=gridInfo.get(row);
- if(gridRow!=null&&column>=0&&column<gridRow.size()){
- Pointpoint=gridRow.get(column);
- if(point!=null)
- returnpoint.y;
- }
- }
- return1;
- }
- protectedbooleansetGrid(introw,intcolumn,Pointgrid){
- if(gridInfo!=null&&row>=0&&row<gridInfo.size()){
- List<Point>gridRow=gridInfo.get(row);
- if(gridRow!=null&&column>=0&&column<gridRow.size()){
- Pointpoint=gridRow.get(column);
- if(point!=null){
- point.setLocation(grid);
- }
- else{
- gridRow.set(column,grid.getLocation());
- }
- returntrue;
- }
- }
- returnfalse;
- }
- @Override
- publicbooleanspliteCellAt(introw,intcolumn){
- if(gridInfo!=null&&row>=0&&row<gridInfo.size()){
- List<Point>gridRow=gridInfo.get(row);
- if(gridRow!=null&&column>=0&&column<gridRow.size()){
- Pointpoint=gridRow.get(column);
- if(point!=null){
- point=point.getLocation();
- for(inta=0;a<point.y;a++){
- for(intb=0;b<point.x;b++){
- setGrid(row+a,column+b,getDefaultPoint());
- }
- }
- }
- else{
- gridRow.set(column,getDefaultPoint());
- }
- returntrue;
- }
- }
- returnfalse;
- }
- @Override
- /**
- *table中发生行的添加和删除的时候需要修改该模型
- */
- publicvoidtableChanged(TableModelEvente){
- //TODO
- }
- @Override
- publicbooleanmergeCells(int[]rows,int[]columns){
- if(!canMergeCells(rows,columns))
- returnfalse;
- Arrays.sort(rows);
- Arrays.sort(columns);
- returnmergeCells(rows[0],rows[rows.length-1],columns[0],columns[columns.length-1]);
- }
- @Override
- publicbooleanmergeCells(intstartRow,intendRow,intstartColumn,intendColumn){
- setGrid(startRow,startColumn,newPoint(endColumn-startColumn+1,endRow-startRow+1));
- for(introw=startRow;row<=endRow;row++){
- for(intcol=startColumn;col<=endColumn;col++){
- if(row==startRow&&col==startColumn)
- continue;
- else
- setGrid(row,col,newPoint(COVERED,COVERED));
- }
- }
- returntrue;
- }
- publicStringtoString(){
- if(gridInfo==null)
- return"";
- StringBuffersb=newStringBuffer();
- for(List<Point>rowInfo:gridInfo){
- for(Pointgrid:rowInfo){
- sb.append("["+grid.x+","+grid.y+"],");
- }
- sb.append("\n");
- }
- returnsb.toString();
- }
- }
- packageorg.dxj.guitools.gridbagtable;
- importjava.awt.Color;
- importjava.awt.Component;
- importjava.awt.Dimension;
- importjava.awt.Graphics;
- importjava.awt.Point;
- importjava.awt.Rectangle;
- importjava.util.Enumeration;
- importjavax.swing.BorderFactory;
- importjavax.swing.JComponent;
- importjavax.swing.JTable;
- importjavax.swing.UIManager;
- importjavax.swing.plaf.basic.BasicTableUI;
- importjavax.swing.table.JTableHeader;
- importjavax.swing.table.TableCellRenderer;
- importjavax.swing.table.TableColumn;
- importjavax.swing.table.TableColumnModel;
- publicclassGridBagTableUIextendsBasicTableUI
- {
- publicDimensiongetPreferredSize(JComponentc){
- longwidth=0;
- Enumeration<TableColumn>enumeration=table.getColumnModel().getColumns();
- while(enumeration.hasMoreElements()){
- TableColumnaColumn=(TableColumn)enumeration.nextElement();
- width=width+aColumn.getPreferredWidth();
- }
- returncreateTableSize(width);
- }
- privateDimensioncreateTableSize(longwidth){
- intheight=0;
- introwCount=table.getRowCount();
- if(rowCount>0&&table.getColumnCount()>0){
- Rectangler=table.getCellRect(rowCount-1,0,true);
- height=r.y+r.height;
- }
- //Widthisalwayspositive.Thecalltoabs()isaworkaroundfor
- //abuginthe1.1.6JITonWindows.
- longtmp=Math.abs(width);
- if(tmp>Integer.MAX_VALUE){
- tmp=Integer.MAX_VALUE;
- }
- returnnewDimension((int)tmp,height);
- }
- publicvoidpaint(Graphicsg,JComponentc){
- Rectangleclip=g.getClipBounds();
- Rectanglebounds=table.getBounds();
- //accountforthefactthatthegraphicshasalreadybeentranslated
- //intothetable'sbounds
- bounds.x=bounds.y=0;
- if(table.getRowCount()<=0||table.getColumnCount()<=0||
- //thischeckpreventsusfrompaintingtheentiretable
- //whentheclipdoesn'tintersectourboundsatall
- !bounds.intersects(clip)){
- paintDropLines(g);
- return;
- }
- booleanltr=table.getComponentOrientation().isLeftToRight();
- PointupperLeft=clip.getLocation();
- if(!ltr){
- upperLeft.x++;
- }
- PointlowerRight=newPoint(clip.x+clip.width-(ltr?1:0),
- clip.y+clip.height);
- intrMin=table.rowAtPoint(upperLeft);
- intrMax=table.rowAtPoint(lowerRight);
- //Thisshouldneverhappen(aslongasourboundsintersecttheclip,
- //whichiswhywebailaboveifthatisthecase).
- if(rMin==-1){
- rMin=0;
- }
- //Ifthetabledoesnothaveenoughrowstofilltheviewwe'llget-1.
- //(Wecouldalsoget-1ifourboundsdon'tintersecttheclip,
- //whichiswhywebailaboveifthatisthecase).
- //Replacethiswiththeindexofthelastrow.
- if(rMax==-1){
- rMax=table.getRowCount()-1;
- }
- intcMin=table.columnAtPoint(ltr?upperLeft:lowerRight);
- intcMax=table.columnAtPoint(ltr?lowerRight:upperLeft);
- //Thisshouldneverhappen.
- if(cMin==-1){
- cMin=0;
- }
- //Ifthetabledoesnothaveenoughcolumnstofilltheviewwe'llget-1.
- //Replacethiswiththeindexofthelastcolumn.
- if(cMax==-1){
- cMax=table.getColumnCount()-1;
- }
- //Paintthegrid.
- //paintGrid(g,rMin,rMax,cMin,cMax);
- //Paintthecells.
- paintCells(g,rMin,rMax,cMin,cMax);
- paintDropLines(g);
- }
- privatevoidpaintDropLines(Graphicsg){
- JTable.DropLocationloc=table.getDropLocation();
- if(loc==null){
- return;
- }
- Colorcolor=UIManager.getColor("Table.dropLineColor");
- ColorshortColor=UIManager.getColor("Table.dropLineShortColor");
- if(color==null&&shortColor==null){
- return;
- }
- Rectanglerect;
- rect=getHDropLineRect(loc);
- if(rect!=null){
- intx=rect.x;
- intw=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){
- inty=rect.y;
- inth=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);
- }
- }
- }
- /*
- *Paintsthegridlineswithin<I>aRect</I>,usingthegrid
- *colorsetwith<I>setGridColor</I>.Paintsverticallines
- *if<code>getShowVerticalLines()</code>returnstrueandpaints
- *horizontallinesif<code>getShowHorizontalLines()</code>
- *returnstrue.
- */
- privatevoidpaintGrid(Graphicsg,intrMin,intrMax,intcMin,intcMax){
- g.setColor(table.getGridColor());
- RectangleminCell=table.getCellRect(rMin,cMin,true);
- RectanglemaxCell=table.getCellRect(rMax,cMax,true);
- RectangledamagedArea=minCell.union(maxCell);
- if(table.getShowHorizontalLines()){
- inttableWidth=damagedArea.x+damagedArea.width;
- inty=damagedArea.y;
- for(introw=rMin;row<=rMax;row++){
- y+=table.getRowHeight(row);
- g.drawLine(damagedArea.x,y-1,tableWidth-1,y-1);
- }
- }
- if(table.getShowVerticalLines()){
- TableColumnModelcm=table.getColumnModel();
- inttableHeight=damagedArea.y+damagedArea.height;
- intx;
- if(table.getComponentOrientation().isLeftToRight()){
- x=damagedArea.x;
- for(intcolumn=cMin;column<=cMax;column++){
- intw=cm.getColumn(column).getWidth();
- x+=w;
- g.drawLine(x-1,0,x-1,tableHeight-1);
- }
- }else{
- x=damagedArea.x;
- for(intcolumn=cMax;column>=cMin;column--){
- intw=cm.getColumn(column).getWidth();
- x+=w;
- g.drawLine(x-1,0,x-1,tableHeight-1);
- }
- }
- }
- }
- privatevoidpaintCells(Graphicsg,intrMin,intrMax,intcMin,intcMax){
- JTableHeaderheader=table.getTableHeader();
- TableColumndraggedColumn=(header==null)?null:header.getDraggedColumn();
- TableColumnModelcm=table.getColumnModel();
- intcolumnMargin=cm.getColumnMargin();
- RectanglecellRect;
- TableColumnaColumn;
- intcolumnWidth;
- if(table.getComponentOrientation().isLeftToRight()){
- for(introw=rMin;row<=rMax;row++){
- if(tableinstanceofGridBagTable)
- cellRect=((GridBagTable)table).getGridCellRect(row,cMin,false);
- else
- cellRect=table.getCellRect(row,cMin,false);
- for(intcolumn=cMin;column<=cMax;column++){
- aColumn=cm.getColumn(column);
- columnWidth=aColumn.getWidth();
- //TODO
- cellRect.width=columnWidth-columnMargin;
- intoldHeight=cellRect.height;
- if(tableinstanceofGridBagTable){
- if(((GridBagTable)table).getGridBagModel().getCellState(row,column)==GridBagModel.COVERED){
- cellRect.width=0;
- cellRect.height=0;
- }
- else{
- inth=((GridBagTable)table).getGridBagModel().getColumnGrid(row,column);
- if(h>1){
- for(intn=1;n<h;n++)
- cellRect.width+=cm.getColumn(column+n).getWidth();
- }
- intv=((GridBagTable)table).getGridBagModel().getRowGrid(row,column);
- if(v>1){
- for(intn=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(introw=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(intcolumn=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);
- }
- }
- }
- }
- //Paintthedraggedcolumnifwearedragging.
- if(draggedColumn!=null){
- paintDraggedArea(g,rMin,rMax,draggedColumn,header.getDraggedDistance());
- }
- //RemoveanyrenderersthatmaybeleftintherendererPane.
- rendererPane.removeAll();
- }
- privatevoidpaintCell(Graphicsg,RectanglecellRect,introw,intcolumn){
- if(table.isEditing()&&table.getEditingRow()==row&&
- table.getEditingColumn()==column){
- Componentcomponent=table.getEditorComponent();
- component.setBounds(cellRect);
- component.validate();
- }
- else{
- TableCellRendererrenderer=table.getCellRenderer(row,column);
- Componentcomponent=table.prepareRenderer(renderer,row,column);
- if(componentinstanceofJComponent){
- ((JComponent)component).setBorder(BorderFactory.createLineBorder(Color.gray));
- }
- rendererPane.paintComponent(g,component,table,cellRect.x,cellRect.y,
- cellRect.width,cellRect.height,true);
- }
- }
- privateRectanglegetHDropLineRect(JTable.DropLocationloc){
- if(!loc.isInsertRow()){
- returnnull;
- }
- introw=loc.getRow();
- intcol=loc.getColumn();
- if(col>=table.getColumnCount()){
- col--;
- }
- Rectanglerect=table.getCellRect(row,col,true);
- if(row>=table.getRowCount()){
- row--;
- RectangleprevRect=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;
- returnrect;
- }
- privatevoidpaintDraggedArea(Graphicsg,intrMin,intrMax,TableColumndraggedColumn,intdistance){
- intdraggedColumnIndex=viewIndexForColumn(draggedColumn);
- RectangleminCell=table.getCellRect(rMin,draggedColumnIndex,true);
- RectanglemaxCell=table.getCellRect(rMax,draggedColumnIndex,true);
- RectanglevacatedColumnRect=minCell.union(maxCell);
- //Paintagraywellinplaceofthemovingcolumn.
- g.setColor(table.getParent().getBackground());
- g.fillRect(vacatedColumnRect.x,vacatedColumnRect.y,
- vacatedColumnRect.width,vacatedColumnRect.height);
- //Movetothewherethecellhasbeendragged.
- vacatedColumnRect.x+=distance;
- //Fillthebackground.
- g.setColor(table.getBackground());
- g.fillRect(vacatedColumnRect.x,vacatedColumnRect.y,
- vacatedColumnRect.width,vacatedColumnRect.height);
- //Painttheverticalgridlinesifnecessary.
- if(table.getShowVerticalLines()){
- g.setColor(table.getGridColor());
- intx1=vacatedColumnRect.x;
- inty1=vacatedColumnRect.y;
- intx2=x1+vacatedColumnRect.width-1;
- inty2=y1+vacatedColumnRect.height-1;
- //Left
- g.drawLine(x1-1,y1,x1-1,y2);
- //Right
- g.drawLine(x2,y1,x2,y2);
- }
- for(introw=rMin;row<=rMax;row++){
- //Renderthecellvalue
- Rectangler=table.getCellRect(row,draggedColumnIndex,false);
- r.x+=distance;
- paintCell(g,r,row,draggedColumnIndex);
- //Paintthe(lower)horizontalgridlineifnecessary.
- if(table.getShowHorizontalLines()){
- g.setColor(table.getGridColor());
- Rectanglercr=table.getCellRect(row,draggedColumnIndex,true);
- rcr.x+=distance;
- intx1=rcr.x;
- inty1=rcr.y;
- intx2=x1+rcr.width-1;
- inty2=y1+rcr.height-1;
- g.drawLine(x1,y2,x2,y2);
- }
- }
- }
- privateintviewIndexForColumn(TableColumnaColumn){
- TableColumnModelcm=table.getColumnModel();
- for(intcolumn=0;column<cm.getColumnCount();column++){
- if(cm.getColumn(column)==aColumn){
- returncolumn;
- }
- }
- return-1;
- }
- privateRectangleextendRect(Rectanglerect,booleanhorizontal){
- if(rect==null){
- returnrect;
- }
- if(horizontal){
- rect.x=0;
- rect.width=table.getWidth();
- }else{
- rect.y=0;
- if(table.getRowCount()!=0){
- RectanglelastRect=table.getCellRect(table.getRowCount()-1,0,true);
- rect.height=lastRect.y+lastRect.height;
- }else{
- rect.height=table.getHeight();
- }
- }
- returnrect;
- }
- privateRectanglegetVDropLineRect(JTable.DropLocationloc){
- if(!loc.isInsertColumn()){
- returnnull;
- }
- booleanltr=table.getComponentOrientation().isLeftToRight();
- intcol=loc.getColumn();
- Rectanglerect=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;
- }
- }elseif(!ltr){
- rect.x=rect.x+rect.width;
- }
- if(rect.x==0){
- rect.x=-1;
- }else{
- rect.x-=2;
- }
- rect.width=3;
- returnrect;
- }
- }//EndofClassBasicTableUI
测试代码:
- importjava.awt.BorderLayout;
- importjava.awt.event.ActionEvent;
- importjava.awt.event.ActionListener;
- importjavax.swing.JButton;
- importjavax.swing.JFrame;
- importjavax.swing.JScrollPane;
- importjavax.swing.table.DefaultTableModel;
- importcom.jrf.jgrid.guitools.gridbagtable.GridBagTable;
- publicclassTestimplementsActionListener{
- GridBagTabletable;
- publicTest()
- {
- JFramed=newJFrame();
- DefaultTableModelmodel=newDefaultTableModel(5,5);
- table=newGridBagTable(model);
- table.setRowHeight(20);
- JScrollPanepane=newJScrollPane(table);
- d.getContentPane().add(pane,BorderLayout.CENTER);
- JButtonbtn=newJButton("合并/拆分");
- d.getContentPane().add(btn,BorderLayout.NORTH);
- btn.addActionListener(this);
- d.setBounds(0,0,400,400);
- d.setVisible(true);
- }
- publicstaticvoidmain(String[]fsd){
- newTest();
- }
- publicvoidactionPerformed(ActionEvente){
- table.mergeCells(table.getSelectedRows(),table.getSelectedColumns());
- }
- }年前在网上参加了一个JavaSwing的招聘上机考试。招聘方要求开发一个类似EXCEL支持单元格合并的JTable。差不多用了5天的时间提交代码,最后被告知测试通过,我提出是否可做兼职,对方回复需要到上海做全职开发,最后也就放弃了。最近公司的一个项目中需要用到以前的代码,偶又重构了一次,设计思想来源于ListSelectionModel。
GridBagModel:抽象模型接口。该接口用于描述表格中单元格的合并状态。
DefaultGridBagTableModel:GridBagModel的默认实现。
GridBagTable:继承自JTable的控制器。通过该类中的方法控制表格单元的合并和拆分。
GridBagTableUI:GridBagTable对应的UI。
TODO:(已合并)行、列的插入,删除操作对应的GridBagModel的修改,不过已留接口。- packageorg.dxj.guitools.gridbagtable;
- importjava.awt.Component;
- importjava.awt.Point;
- importjava.awt.Rectangle;
- importjava.util.Enumeration;
- importjava.util.EventObject;
- importjavax.swing.DefaultCellEditor;
- importjavax.swing.JTable;
- importjavax.swing.SwingUtilities;
- importjavax.swing.event.TableModelEvent;
- importjavax.swing.table.AbstractTableModel;
- importjavax.swing.table.TableColumn;
- importjavax.swing.table.TableColumnModel;
- /**
- *@author15860102@qq.com
- */
- publicclassGridBagTableextendsJTable{
- GridBagModelgridBagModel;
- publicGridBagModelgetGridBagModel(){
- returngridBagModel;
- }
- publicvoidsetGridBagModel(GridBagModelgridBagModel){
- if(gridBagModel!=null&&gridBagModel!=this.gridBagModel)
- this.gridBagModel=gridBagModel;
- }
- publicGridBagTable(AbstractTableModeldm){
- super(dm);
- getTableHeader().setReorderingAllowed(false);
- gridBagModel=newDefaultGridBagTableModel(dm);
- getColumnModel().setColumnSelectionAllowed(true);
- }
- privatevoidupdateSubComponentUI(ObjectcomponentShell){
- if(componentShell==null){
- return;
- }
- Componentcomponent=null;
- if(componentShellinstanceofComponent){
- component=(Component)componentShell;
- }
- if(componentShellinstanceofDefaultCellEditor){
- component=((DefaultCellEditor)componentShell).getComponent();
- }
- if(component!=null){
- SwingUtilities.updateComponentTreeUI(component);
- }
- }
- publicvoidupdateUI(){
- //UpdatetheUIsofthecellrenderers,celleditorsandheaderrenderers.
- TableColumnModelcm=getColumnModel();
- for(intcolumn=0;column<cm.getColumnCount();column++){
- TableColumnaColumn=cm.getColumn(column);
- updateSubComponentUI(aColumn.getCellRenderer());
- updateSubComponentUI(aColumn.getCellEditor());
- updateSubComponentUI(aColumn.getHeaderRenderer());
- }
- //UpdatetheUIsofallthedefaultrenderers.
- EnumerationdefaultRenderers=defaultRenderersByColumnClass.elements();
- while(defaultRenderers.hasMoreElements()){
- updateSubComponentUI(defaultRenderers.nextElement());
- }
- //UpdatetheUIsofallthedefaulteditors.
- EnumerationdefaultEditors=defaultEditorsByColumnClass.elements();
- while(defaultEditors.hasMoreElements()){
- updateSubComponentUI(defaultEditors.nextElement());
- }
- //UpdatetheUIofthetableheader
- if(tableHeader!=null&&tableHeader.getParent()==null){
- tableHeader.updateUI();
- }
- setUI(newGridBagTableUI());
- }
- publicRectanglegetGridCellRect(introw,intcolumn,booleanincludeSpacing){
- returnsuper.getCellRect(row,column,includeSpacing);
- }
- publicRectanglegetCellRect(introw,intcolumn,booleanincludeSpacing){
- RectanglecellRect=super.getCellRect(row,column,includeSpacing);
- intcols=gridBagModel.getColumnGrid(row,column);
- TableColumnModelcm=getColumnModel();
- for(intn=1;n<cols;n++)
- cellRect.width+=cm.getColumn(column+n).getWidth();
- introws=gridBagModel.getRowGrid(row,column);
- for(intn=1;n<rows;n++)
- cellRect.height+=getRowHeight(row+n);
- returncellRect;
- }
- publicvoidtableChanged(TableModelEvente){
- super.tableChanged(e);
- //TODO
- }
- publicbooleanmergeCells(intstartRow,intendRow,intstartColumn,intendColumn){
- if(gridBagModel.mergeCells(startRow,endRow,startColumn,endColumn)){
- repaint();
- returntrue;
- }
- returnfalse;
- }
- publicbooleanmergeCells(int[]rows,int[]columns){
- if(gridBagModel.mergeCells(rows,columns)){
- repaint();
- returntrue;
- }
- returnfalse;
- }
- publicbooleanspliteCellAt(introw,intcolumn){
- if(gridBagModel.spliteCellAt(row,column)){
- repaint();
- returntrue;
- }
- returnfalse;
- }
- publicvoidchangeSelection(introwIndex,intcolumnIndex,booleantoggle,booleanextend){
- if(gridBagModel.getCellState(rowIndex,columnIndex)!=GridBagModel.COVERED)
- super.changeSelection(rowIndex,columnIndex,toggle,extend);
- Pointp;
- for(introw=rowIndex;row>=0;row--){
- for(intcol=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();
- }
- publicbooleaneditCellAt(introwIndex,intcolumnIndex,EventObjecte){
- if(gridBagModel.getCellState(rowIndex,columnIndex)!=GridBagModel.COVERED)
- returnsuper.editCellAt(rowIndex,columnIndex,e);
- Pointp;
- for(introw=rowIndex;row>=0;row--){
- for(intcol=columnIndex;col>=0;col--){
- p=gridBagModel.getGrid(row,col);
- if(col+p.x>columnIndex&&row+p.y>rowIndex){
- rowIndex=row;
- columnIndex=col;
- break;
- }
- }
- }
- returnsuper.editCellAt(rowIndex,columnIndex,e);
- }
- }
- packageorg.dxj.guitools.gridbagtable;
- importjava.awt.Point;
- publicinterfaceGridBagModel{
- //格子处于正常状态
- intDEFAULT=0;
- //格子合并了其他的格子
- intMERGE=1;
- //格子被其他格子合并
- intCOVERED=-1;
- /**
- *@paramrow行
- *@paramcolumn列
- *@return该单元格在行、列的跨度
- */
- PointgetGrid(introw,intcolumn);
- /**
- *在Y轴方向的跨度
- *@paramrow
- *@paramcolumn
- *@return
- */
- intgetRowGrid(introw,intcolumn);
- /**
- *在X轴方向的跨度
- *@paramrow
- *@paramcolumn
- *@return
- */
- intgetColumnGrid(introw,intcolumn);
- /**
- *@paramrows行集合
- *@paramcolumns列集合
- *@return单元格集合是否可以合并在一起
- */
- booleancanMergeCells(int[]rows,int[]columns);
- /**
- *判断该单元格状态
- *@paramrow
- *@paramcolumn
- *@returnMERGE|DEFAULT|COVERED
- */
- intgetCellState(introw,intcolumn);
- /**
- *将单元格集合合并
- *@paramstartRow开始行
- *@paramendRow结束行
- *@paramstartColumn开始列
- *@paramendColumn结束列
- *@return是否合并成功
- */
- booleanmergeCells(intstartRow,intendRow,intstartColumn,intendColumn);
- /**
- *将单元格集合合并
- *@paramrows行集合
- *@paramcolumns列集合
- *@return是否合并成功
- */
- booleanmergeCells(int[]rows,int[]columns);
- /**
- *拆分单元格
- *@paramrow行
- *@paramcolumn列
- *@return是否拆分成功
- */
- booleanspliteCellAt(introw,intcolumn);
- /**
- *清除所有合并
- */
- voidclearMergence();
- }
- packageorg.dxj.guitools.gridbagtable;
- importjava.awt.Point;
- importjava.util.Arrays;
- importjava.util.List;
- importjava.util.Vector;
- importjavax.swing.event.TableModelEvent;
- importjavax.swing.event.TableModelListener;
- importjavax.swing.table.AbstractTableModel;
- publicclassDefaultGridBagTableModelimplementsGridBagModel,TableModelListener{
- protectedAbstractTableModelmodel;
- protectedList<List<Point>>gridInfo;
- DefaultGridBagTableModel(AbstractTableModelmodel){
- gridInfo=newVector<List<Point>>();
- setTableModel(model);
- }
- publicvoidsetTableModel(AbstractTableModelmodel){
- if(model!=null&&model!=this.model){
- if(this.model!=null)
- this.model.removeTableModelListener(this);
- //防止多次添加监听器
- model.removeTableModelListener(this);
- model.addTableModelListener(this);
- this.model=model;
- clearMergence();
- }
- }
- publicvoidclearMergence(){
- if(gridInfo==null)
- gridInfo=newVector<List<Point>>();
- else
- gridInfo.clear();
- if(model==null)
- return;
- //初始化,每个格子占的格子数为(1,1);
- for(introw=model.getRowCount();--row>=0;){
- List<Point>infos=newVector<Point>();
- gridInfo.add(infos);
- for(intcol=model.getColumnCount();--col>=0;){
- infos.add(getDefaultPoint());
- }
- }
- }
- publicPointgetDefaultPoint(){
- returnnewPoint(1,1);
- }
- @Override
- publicbooleancanMergeCells(int[]rows,int[]columns){
- if(rows==null||columns==null)returnfalse;
- Arrays.sort(rows);
- for(intindex=0;index<rows.length-1;index++){
- if(rows[index+1]-rows[index]>1)
- returnfalse;
- }
- Arrays.sort(columns);
- for(intindex=0;index<columns.length-1;index++){
- if(columns[index+1]-columns[index]>1)
- returnfalse;
- }
- returntrue;
- }
- @Override
- publicintgetCellState(introw,intcolumn){
- Pointgrid=getGrid(row,column);
- if(grid==null)returnDEFAULT;
- if(grid.x>1||grid.y>1)
- returnMERGE;
- if(grid.x<=0||grid.y<=0)
- returnCOVERED;
- returnDEFAULT;
- }
- @Override
- publicintgetColumnGrid(introw,intcolumn){
- if(gridInfo!=null&&row>=0&&row<gridInfo.size()){
- List<Point>gridRow=gridInfo.get(row);
- if(gridRow!=null&&column>=0&&column<gridRow.size()){
- Pointpoint=gridRow.get(column);
- if(point!=null)
- returnpoint.x;
- }
- }
- return1;
- }
- @Override
- publicPointgetGrid(introw,intcolumn){
- if(gridInfo!=null&&row>=0&&row<gridInfo.size()){
- List<Point>gridRow=gridInfo.get(row);
- if(gridRow!=null&&column>=0&&column<gridRow.size()){
- returngridRow.get(column);
- }
- }
- returngetDefaultPoint();
- }
- @Override
- publicintgetRowGrid(introw,intcolumn){
- if(gridInfo!=null&&row>=0&&row<gridInfo.size()){
- List<Point>gridRow=gridInfo.get(row);
- if(gridRow!=null&&column>=0&&column<gridRow.size()){
- Pointpoint=gridRow.get(column);
- if(point!=null)
- returnpoint.y;
- }
- }
- return1;
- }
- protectedbooleansetGrid(introw,intcolumn,Pointgrid){
- if(gridInfo!=null&&row>=0&&row<gridInfo.size()){
- List<Point>gridRow=gridInfo.get(row);
- if(gridRow!=null&&column>=0&&column<gridRow.size()){
- Pointpoint=gridRow.get(column);
- if(point!=null){
- point.setLocation(grid);
- }
- else{
- gridRow.set(column,grid.getLocation());
- }
- returntrue;
- }
- }
- returnfalse;
- }
- @Override
- publicbooleanspliteCellAt(introw,intcolumn){
- if(gridInfo!=null&&row>=0&&row<gridInfo.size()){
- List<Point>gridRow=gridInfo.get(row);
- if(gridRow!=null&&column>=0&&column<gridRow.size()){
- Pointpoint=gridRow.get(column);
- if(point!=null){
- point=point.getLocation();
- for(inta=0;a<point.y;a++){
- for(intb=0;b<point.x;b++){
- setGrid(row+a,column+b,getDefaultPoint());
- }
- }
- }
- else{
- gridRow.set(column,getDefaultPoint());
- }
- returntrue;
- }
- }
- returnfalse;
- }
- @Override
- /**
- *table中发生行的添加和删除的时候需要修改该模型
- */
- publicvoidtableChanged(TableModelEvente){
- //TODO
- }
- @Override
- publicbooleanmergeCells(int[]rows,int[]columns){
- if(!canMergeCells(rows,columns))
- returnfalse;
- Arrays.sort(rows);
- Arrays.sort(columns);
- returnmergeCells(rows[0],rows[rows.length-1],columns[0],columns[columns.length-1]);
- }
- @Override
- publicbooleanmergeCells(intstartRow,intendRow,intstartColumn,intendColumn){
- setGrid(startRow,startColumn,newPoint(endColumn-startColumn+1,endRow-startRow+1));
- for(introw=startRow;row<=endRow;row++){
- for(intcol=startColumn;col<=endColumn;col++){
- if(row==startRow&&col==startColumn)
- continue;
- else
- setGrid(row,col,newPoint(COVERED,COVERED));
- }
- }
- returntrue;
- }
- publicStringtoString(){
- if(gridInfo==null)
- return"";
- StringBuffersb=newStringBuffer();
- for(List<Point>rowInfo:gridInfo){
- for(Pointgrid:rowInfo){
- sb.append("["+grid.x+","+grid.y+"],");
- }
- sb.append("\n");
- }
- returnsb.toString();
- }
- }
- packageorg.dxj.guitools.gridbagtable;
- importjava.awt.Color;
- importjava.awt.Component;
- importjava.awt.Dimension;
- importjava.awt.Graphics;
- importjava.awt.Point;
- importjava.awt.Rectangle;
- importjava.util.Enumeration;
- importjavax.swing.BorderFactory;
- importjavax.swing.JComponent;
- importjavax.swing.JTable;
- importjavax.swing.UIManager;
- importjavax.swing.plaf.basic.BasicTableUI;
- importjavax.swing.table.JTableHeader;
- importjavax.swing.table.TableCellRenderer;
- importjavax.swing.table.TableColumn;
- importjavax.swing.table.TableColumnModel;
- publicclassGridBagTableUIextendsBasicTableUI
- {
- publicDimensiongetPreferredSize(JComponentc){
- longwidth=0;
- Enumeration<TableColumn>enumeration=table.getColumnModel().getColumns();
- while(enumeration.hasMoreElements()){
- TableColumnaColumn=(TableColumn)enumeration.nextElement();
- width=width+aColumn.getPreferredWidth();
- }
- returncreateTableSize(width);
- }
- privateDimensioncreateTableSize(longwidth){
- intheight=0;
- introwCount=table.getRowCount();
- if(rowCount>0&&table.getColumnCount()>0){
- Rectangler=table.getCellRect(rowCount-1,0,true);
- height=r.y+r.height;
- }
- //Widthisalwayspositive.Thecalltoabs()isaworkaroundfor
- //abuginthe1.1.6JITonWindows.
- longtmp=Math.abs(width);
- if(tmp>Integer.MAX_VALUE){
- tmp=Integer.MAX_VALUE;
- }
- returnnewDimension((int)tmp,height);
- }
- publicvoidpaint(Graphicsg,JComponentc){
- Rectangleclip=g.getClipBounds();
- Rectanglebounds=table.getBounds();
- //accountforthefactthatthegraphicshasalreadybeentranslated
- //intothetable'sbounds
- bounds.x=bounds.y=0;
- if(table.getRowCount()<=0||table.getColumnCount()<=0||
- //thischeckpreventsusfrompaintingtheentiretable
- //whentheclipdoesn'tintersectourboundsatall
- !bounds.intersects(clip)){
- paintDropLines(g);
- return;
- }
- booleanltr=table.getComponentOrientation().isLeftToRight();
- PointupperLeft=clip.getLocation();
- if(!ltr){
- upperLeft.x++;
- }
- PointlowerRight=newPoint(clip.x+clip.width-(ltr?1:0),
- clip.y+clip.height);
- intrMin=table.rowAtPoint(upperLeft);
- intrMax=table.rowAtPoint(lowerRight);
- //Thisshouldneverhappen(aslongasourboundsintersecttheclip,
- //whichiswhywebailaboveifthatisthecase).
- if(rMin==-1){
- rMin=0;
- }
- //Ifthetabledoesnothaveenoughrowstofilltheviewwe'llget-1.
- //(Wecouldalsoget-1ifourboundsdon'tintersecttheclip,
- //whichiswhywebailaboveifthatisthecase).
- //Replacethiswiththeindexofthelastrow.
- if(rMax==-1){
- rMax=table.getRowCount()-1;
- }
- intcMin=table.columnAtPoint(ltr?upperLeft:lowerRight);
- intcMax=table.columnAtPoint(ltr?lowerRight:upperLeft);
- //Thisshouldneverhappen.
- if(cMin==-1){
- cMin=0;
- }
- //Ifthetabledoesnothaveenoughcolumnstofilltheviewwe'llget-1.
- //Replacethiswiththeindexofthelastcolumn.
- if(cMax==-1){
- cMax=table.getColumnCount()-1;
- }
- //Paintthegrid.
- //paintGrid(g,rMin,rMax,cMin,cMax);
- //Paintthecells.
- paintCells(g,rMin,rMax,cMin,cMax);
- paintDropLines(g);
- }
- privatevoidpaintDropLines(Graphicsg){
- JTable.DropLocationloc=table.getDropLocation();
- if(loc==null){
- return;
- }
- Colorcolor=UIManager.getColor("Table.dropLineColor");
- ColorshortColor=UIManager.getColor("Table.dropLineShortColor");
- if(color==null&&shortColor==null){
- return;
- }
- Rectanglerect;
- rect=getHDropLineRect(loc);
- if(rect!=null){
- intx=rect.x;
- intw=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){
- inty=rect.y;
- inth=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);
- }
- }
- }
- /*
- *Paintsthegridlineswithin<I>aRect</I>,usingthegrid
- *colorsetwith<I>setGridColor</I>.Paintsverticallines
- *if<code>getShowVerticalLines()</code>returnstrueandpaints
- *horizontallinesif<code>getShowHorizontalLines()</code>
- *returnstrue.
- */
- privatevoidpaintGrid(Graphicsg,intrMin,intrMax,intcMin,intcMax){
- g.setColor(table.getGridColor());
- RectangleminCell=table.getCellRect(rMin,cMin,true);
- RectanglemaxCell=table.getCellRect(rMax,cMax,true);
- RectangledamagedArea=minCell.union(maxCell);
- if(table.getShowHorizontalLines()){
- inttableWidth=damagedArea.x+damagedArea.width;
- inty=damagedArea.y;
- for(introw=rMin;row<=rMax;row++){
- y+=table.getRowHeight(row);
- g.drawLine(damagedArea.x,y-1,tableWidth-1,y-1);
- }
- }
- if(table.getShowVerticalLines()){
- TableColumnModelcm=table.getColumnModel();
- inttableHeight=damagedArea.y+damagedArea.height;
- intx;
- if(table.getComponentOrientation().isLeftToRight()){
- x=damagedArea.x;
- for(intcolumn=cMin;column<=cMax;column++){
- intw=cm.getColumn(column).getWidth();
- x+=w;
- g.drawLine(x-1,0,x-1,tableHeight-1);
- }
- }else{
- x=damagedArea.x;
- for(intcolumn=cMax;column>=cMin;column--){
- intw=cm.getColumn(column).getWidth();
- x+=w;
- g.drawLine(x-1,0,x-1,tableHeight-1);
- }
- }
- }
- }
- privatevoidpaintCells(Graphicsg,intrMin,intrMax,intcMin,intcMax){
- JTableHeaderheader=table.getTableHeader();
- TableColumndraggedColumn=(header==null)?null:header.getDraggedColumn();
- TableColumnModelcm=table.getColumnModel();
- intcolumnMargin=cm.getColumnMargin();
- RectanglecellRect;
- TableColumnaColumn;
- intcolumnWidth;
- if(table.getComponentOrientation().isLeftToRight()){
- for(introw=rMin;row<=rMax;row++){
- if(tableinstanceofGridBagTable)
- cellRect=((GridBagTable)table).getGridCellRect(row,cMin,false);
- else
- cellRect=table.getCellRect(row,cMin,false);
- for(intcolumn=cMin;column<=cMax;column++){
- aColumn=cm.getColumn(column);
- columnWidth=aColumn.getWidth();
- //TODO
- cellRect.width=columnWidth-columnMargin;
- intoldHeight=cellRect.height;
- if(tableinstanceofGridBagTable){
- if(((GridBagTable)table).getGridBagModel().getCellState(row,column)==GridBagModel.COVERED){
- cellRect.width=0;
- cellRect.height=0;
- }
- else{
- inth=((GridBagTable)table).getGridBagModel().getColumnGrid(row,column);
- if(h>1){
- for(intn=1;n<h;n++)
- cellRect.width+=cm.getColumn(column+n).getWidth();
- }
- intv=((GridBagTable)table).getGridBagModel().getRowGrid(row,column);
- if(v>1){
- for(intn=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(introw=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(intcolumn=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);
- }
- }
- }
- }
- //Paintthedraggedcolumnifwearedragging.
- if(draggedColumn!=null){
- paintDraggedArea(g,rMin,rMax,draggedColumn,header.getDraggedDistance());
- }
- //RemoveanyrenderersthatmaybeleftintherendererPane.
- rendererPane.removeAll();
- }
- privatevoidpaintCell(Graphicsg,RectanglecellRect,introw,intcolumn){
- if(table.isEditing()&&table.getEditingRow()==row&&
- table.getEditingColumn()==column){
- Componentcomponent=table.getEditorComponent();
- component.setBounds(cellRect);
- component.validate();
- }
- else{
- TableCellRendererrenderer=table.getCellRenderer(row,column);
- Componentcomponent=table.prepareRenderer(renderer,row,column);
- if(componentinstanceofJComponent){
- ((JComponent)component).setBorder(BorderFactory.createLineBorder(Color.gray));
- }
- rendererPane.paintComponent(g,component,table,cellRect.x,cellRect.y,
- cellRect.width,cellRect.height,true);
- }
- }
- privateRectanglegetHDropLineRect(JTable.DropLocationloc){
- if(!loc.isInsertRow()){
- returnnull;
- }
- introw=loc.getRow();
- intcol=loc.getColumn();
- if(col>=table.getColumnCount()){
- col--;
- }
- Rectanglerect=table.getCellRect(row,col,true);
- if(row>=table.getRowCount()){
- row--;
- RectangleprevRect=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;
- returnrect;
- }
- privatevoidpaintDraggedArea(Graphicsg,intrMin,intrMax,TableColumndraggedColumn,intdistance){
- intdraggedColumnIndex=viewIndexForColumn(draggedColumn);
- RectangleminCell=table.getCellRect(rMin,draggedColumnIndex,true);
- RectanglemaxCell=table.getCellRect(rMax,draggedColumnIndex,true);
- RectanglevacatedColumnRect=minCell.union(maxCell);
- //Paintagraywellinplaceofthemovingcolumn.
- g.setColor(table.getParent().getBackground());
- g.fillRect(vacatedColumnRect.x,vacatedColumnRect.y,
- vacatedColumnRect.width,vacatedColumnRect.height);
- //Movetothewherethecellhasbeendragged.
- vacatedColumnRect.x+=distance;
- //Fillthebackground.
- g.setColor(table.getBackground());
- g.fillRect(vacatedColumnRect.x,vacatedColumnRect.y,
- vacatedColumnRect.width,vacatedColumnRect.height);
- //Painttheverticalgridlinesifnecessary.
- if(table.getShowVerticalLines()){
- g.setColor(table.getGridColor());
- intx1=vacatedColumnRect.x;
- inty1=vacatedColumnRect.y;
- intx2=x1+vacatedColumnRect.width-1;
- inty2=y1+vacatedColumnRect.height-1;
- //Left
- g.drawLine(x1-1,y1,x1-1,y2);
- //Right
- g.drawLine(x2,y1,x2,y2);
- }
- for(introw=rMin;row<=rMax;row++){
- //Renderthecellvalue
- Rectangler=table.getCellRect(row,draggedColumnIndex,false);
- r.x+=distance;
- paintCell(g,r,row,draggedColumnIndex);
- //Paintthe(lower)horizontalgridlineifnecessary.
- if(table.getShowHorizontalLines()){
- g.setColor(table.getGridColor());
- Rectanglercr=table.getCellRect(row,draggedColumnIndex,true);
- rcr.x+=distance;
- intx1=rcr.x;
- inty1=rcr.y;
- intx2=x1+rcr.width-1;
- inty2=y1+rcr.height-1;
- g.drawLine(x1,y2,x2,y2);
- }
- }
- }
- privateintviewIndexForColumn(TableColumnaColumn){
- TableColumnModelcm=table.getColumnModel();
- for(intcolumn=0;column<cm.getColumnCount();column++){
- if(cm.getColumn(column)==aColumn){
- returncolumn;
- }
- }
- return-1;
- }
- privateRectangleextendRect(Rectanglerect,booleanhorizontal){
- if(rect==null){
- returnrect;
- }
- if(horizontal){
- rect.x=0;
- rect.width=table.getWidth();
- }else{
- rect.y=0;
- if(table.getRowCount()!=0){
- RectanglelastRect=table.getCellRect(table.getRowCount()-1,0,true);
- rect.height=lastRect.y+lastRect.height;
- }else{
- rect.height=table.getHeight();
- }
- }
- returnrect;
- }
- privateRectanglegetVDropLineRect(JTable.DropLocationloc){
- if(!loc.isInsertColumn()){
- returnnull;
- }
- booleanltr=table.getComponentOrientation().isLeftToRight();
- intcol=loc.getColumn();
- Rectanglerect=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;
- }
- }elseif(!ltr){
- rect.x=rect.x+rect.width;
- }
- if(rect.x==0){
- rect.x=-1;
- }else{
- rect.x-=2;
- }
- rect.width=3;
- returnrect;
- }
- }//EndofClassBasicTableUI
测试代码:
- importjava.awt.BorderLayout;
- importjava.awt.event.ActionEvent;
- importjava.awt.event.ActionListener;
- importjavax.swing.JButton;
- importjavax.swing.JFrame;
- importjavax.swing.JScrollPane;
- importjavax.swing.table.DefaultTableModel;
- importcom.jrf.jgrid.guitools.gridbagtable.GridBagTable;
- publicclassTestimplementsActionListener{
- GridBagTabletable;
- publicTest()
- {
- JFramed=newJFrame();
- DefaultTableModelmodel=newDefaultTableModel(5,5);
- table=newGridBagTable(model);
- table.setRowHeight(20);
- JScrollPanepane=newJScrollPane(table);
- d.getContentPane().add(pane,BorderLayout.CENTER);
- JButtonbtn=newJButton("合并/拆分");
- d.getContentPane().add(btn,BorderLayout.NORTH);
- btn.addActionListener(this);
- d.setBounds(0,0,400,400);
- d.setVisible(true);
- }
- publicstaticvoidmain(String[]fsd){
- newTest();
- }
- publicvoidactionPerformed(ActionEvente){
- table.mergeCells(table.getSelectedRows(),table.getSelectedColumns());
- }
- }