- 浏览: 11420 次
- 性别:
- 来自: 北京
文章分类
最新评论
-
jsruth:
感谢分享,学习啦
Java Swing写的支持合并单元格的JTable -
jtlaaa:
...
Java Swing写的支持合并单元格的JTable -
Atlantisbai:
很好的东东,楼主很无私呀,哈哈!!
Java Swing写的支持合并单元格的JTable -
lg_asus:
后輩來取經了
Java Swing写的支持合并单元格的JTable -
tiger860709:
呵呵,不错,好东西,我们项目中也用到了,
Java Swing写的支持合并单元格的JTable
N年前在网上参加了一个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.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
测试代码:
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()); } }
- table.jar (8 KB)
- 下载次数: 777
评论
8 楼
jsruth
2013-04-26
感谢分享,学习啦
7 楼
jtlaaa
2012-07-02
6 楼
Atlantisbai
2012-06-14
很好的东东,楼主很无私呀,哈哈!!
5 楼
lg_asus
2011-04-17
后輩來取經了
4 楼
tiger860709
2010-09-08
呵呵,不错,好东西,我们项目中也用到了,
3 楼
su1216
2010-09-07
曾经用js写过一个合并,拆分
很麻烦。。。
很麻烦。。。
2 楼
iyjc2004
2010-08-24
这个很猛,顶下。JTable是学好swing重中之重啊
1 楼
daimojingdeyu
2010-08-20
写得蛮好,代码有点长,没能仔细看,先支持一下
相关推荐
Swing JTable组件设置单元格合并,内置Test测试类,核心API GridBagTable tasktable = new GridBagTable(model); tasktable.mergeCells(startRow, endRow, 0, 0);
`CombineTable.java`可能是自定义的JTable子类,它扩展了`javax.swing.JTable`,并可能包含一些特定于合并单元格的方法或属性。这个类可以用来协调UI、渲染器和数据模型之间的通信,确保它们在处理合并单元格时保持...
当你需要在`JTable`中实现特定的布局或者展示特殊格式的数据时,可能会遇到需要合并单元格的需求。例如,为了创建一个标题行或列,或者在某些情况下合并具有相同数据的单元格以减少重复,合并单元格就显得尤为重要。...
该接口用于描述表格中单元格的合并状态。 DefaultGridBagTableModel:GridBagModel的默认实现。 GridBagTable:继承自JTable的控制器。通过该类中的方法控制表格单元的合并和拆分。 GridBagTableUI:GridBagTable...
首先,我们要区分两个主要场景:在GUI应用程序(如JavaFX或Swing)中合并单元格与在处理Excel文件(使用Apache POI)时合并单元格。这两种情况的方法略有不同。 1. **JavaFX或Swing中的单元格合并** 在JavaFX中,...
在Java Swing应用开发中,`JTable`是一个非常重要的组件,用于展示二维表格数据。它提供了丰富的功能,如数据编辑、排序、选择等。而"JTable表头合并"是Swing中的一个高级特性,允许开发者创建具有复杂结构的表头,...
在Java Swing库中,JTable是一个非常重要的组件,用于显示和操作二维数据集。这个组件在用户界面设计中广泛使用,因为它提供了丰富的交互性,包括排序、选择和编辑表格数据。"复杂JTable-跨列表头"是一个特殊实现,...
当我们谈论“Swing JTable 合并”,通常是指在`JTable`中合并单元格,以实现更复杂的布局或者展示具有汇总信息的表格。 在`JTable`中,合并单元格涉及到两个主要方面:行合并和列合并。行合并通常用于显示具有多个...
在Java的Swing库中,`JTable`是用于创建数据网格视图的重要组件,它允许用户以表格的形式展示和操作数据。`JTable`在GUI应用中非常常见,尤其适用于展示结构化数据,比如数据库记录或者报表。在这个例子中,我们将...
`getValueAt()`方法需要根据逻辑数据来返回正确的单元格值,包括合并单元格的情况。 **3. 示例代码** 下面是一段简单的代码示例,展示了如何创建一个具有复杂表头和跨行列表体的`JTable`: ```java import javax....
这可能涉及计算合并单元格的总宽度,并相应地调整相关列的宽度。 以下是一个简单的源码示例,展示了如何实现表头合并: ```java public class CustomTableHeaderRenderer extends DefaultTableHeaderCellRenderer ...
例如,我们可能需要检查当前列的索引,并根据索引来决定是否合并单元格。 2. **设置表头渲染器**: 创建了自定义渲染器后,将其设置到`JTableHeader`上。可以使用`JTableHeader.setDefaultRenderer`方法来完成此...
总结来说,实现JTable的单元格合并需要对Swing组件模型有深入理解,尤其是JTable的工作原理。通过定制CellRenderer和调整表格模型,我们可以创造出满足各种需求的表格布局。"MulitiTable"项目提供了一个很好的示例,...
通过学习以上知识点,你将能够创建一个能够合并单元格的`JTable`实例。在压缩包文件中提供的"Swing实例下载"很可能是包含了这些功能的示例代码,可以帮助你更好地理解和实践这个功能。记得阅读和分析代码,理解每个...
4. **高级功能**:如行列拖放、分页、冻结列、合并单元格、自定义列宽等。 5. **事件处理**:可能提供了更加方便的事件监听和处理机制,使得对用户交互的响应更加简单。 6. **国际化支持**:方便进行多语言切换。 7....
在Java编程领域,Swing库是用于创建图形用户界面(GUI)的重要工具,而`JTable`是Swing中一个核心组件,它用于显示和编辑表格数据。`JTable`实例大全提供了各种实用示例,涵盖了`JTable`的高级功能,如合并表头和...
从压缩包子文件的文件名“表头合并单元格_ JTable Groupable TableHeader - Keep Fighting - 博客频道 - CSDN_NET.mht”来看,这可能是一个关于Java Swing组件JTable的专题。JTable是Java GUI编程中用于展示表格数据...
**jTable是Java Swing库中的一个组件,用于在应用程序中展示和操作表格数据。它提供了丰富的功能,包括数据编辑、排序、过滤以及自定义显示等。深入学习jTable的使用,能够帮助开发者创建用户友好的界面,使得数据的...