天天看点

JTable转载

 转载: 表头合并单元格. JTable Groupable TableHeader

http://blog.csdn.net/bradwoo8621/article/details/1541835

表头合并单元格. 照例不多说了, 看代码吧.

首先需要定义一个接口, 看看表头是怎么合并的

package jtble;

public interface Group {

 public int getRow();

 public int getColumn();

 public int getColumnSpan();

 public int getRowSpan();

 public Object getHeaderValue();

}

 这个和HTML的写法其实一样的. 主要就是每个Cell所在的位置, 占的行列数以及

文字.

接下来是一个默认的实现. 其实不写接口也可以, 因为通常不会对表头做动作的.

package jtble;

public class DefaultGroup implements Group {

 private int row = 0;

 private int column = 0;

 private int rowSpan = 1;

 private int columnSpan = 1;

 private Object headerValue = null;

 public int getRow() {

  return this.row;

 }

 public void setRow(int row) {

  this.row = row;

 }

 public int getColumn() {

  return this.column;

 }

 public void setColumn(int column) {

  this.column = column;

 }

 public int getColumnSpan() {

  return this.columnSpan;

 }

 public void setColumnSpan(int columnSpan) {

  this.columnSpan = columnSpan;

 }

 public int getRowSpan() {

  return this.rowSpan;

 }

 public void setRowSpan(int rowSpan) {

  this.rowSpan = rowSpan;

 }

 public Object getHeaderValue() {

  return this.headerValue;

 }

 public void setHeaderValue(Object headerValue) {

  this.headerValue = headerValue;

 }

}

重写一个表头组件

package jtble;

import java.awt.Component;

import java.awt.Rectangle;

import java.util.ArrayList;

import java.util.List;

import javax.swing.JTable;

import javax.swing.table.JTableHeader;

import javax.swing.table.TableCellRenderer;

import javax.swing.table.TableColumnModel;

@SuppressWarnings("serial")

public class GroupableTableHeader extends JTableHeader {

 private int rowCount = 0;

 private int columnCount = 0;

 private List<Group> groups = new ArrayList<Group>();

 public GroupableTableHeader() {

  // 这个是必须的, 因为如果可以拖动列的位置, 那么一切都完

蛋了.

  // 如果你想实现这个功能, 那么只能你自己去做了, 我可不想

做这个, 看上去超烦的

  this.setReorderingAllowed(false);

 }

 @Override

 public void updateUI() {

  setUI(new GroupableTableHeaderUI());

 }

 public Rectangle getHeaderRect(int row, int column) {

  Rectangle r = new Rectangle();

  TableColumnModel cm = getColumnModel();

  Group group = this.getGroup(row, column);

  r.height = getHeight();

  if (column < 0) {

   // x = width = 0;

   if (!getComponentOrientation().isLeftToRight()) {

    r.x = getWidthInRightToLeft();

   }

  } else if (column >= cm.getColumnCount()) {

   if (getComponentOrientation().isLeftToRight()) {

    r.x = getWidth();

   }

  } else {

   for (int i = 0; i < group.getColumn(); i++) {

    r.x += cm.getColumn(i).getWidth();

   }

   for (int i = group.getColumn(), j =

group.getColumn() +

   group.getColumnSpan() - 1; i < j; i++) {

    r.width += cm.getColumn(i).getWidth();

   }

   if (!getComponentOrientation().isLeftToRight()) {

    r.x = getWidthInRightToLeft() - r.x -

r.width;

   }

   // r.width = cm.getColumn(column).getWidth();

  }

  return r;

 }

 public int getYOfGroup(Group group) {

  int row = group.getRow();

  TableCellRenderer renderer = this.getDefaultRenderer();

  Component comp =

renderer.getTableCellRendererComponent(getTable

  (), group.getHeaderValue(), false, false, group.getRow(),

group

    .getColumn());

  return row * comp.getPreferredSize().height;

 }

 public int getHeightOfGroup(Group group) {

  int rowSpan = group.getRowSpan();

  TableCellRenderer renderer = this.getDefaultRenderer();

  Component comp =

renderer.getTableCellRendererComponent(getTable

  (), group.getHeaderValue(), false, false, group.getRow(),

group

    .getColumn());

  return rowSpan * comp.getPreferredSize().height;

 }

 private int getWidthInRightToLeft() {

  if ((table != null) && (table.getAutoResizeMode() !=

  JTable.AUTO_RESIZE_OFF)) {

   return table.getWidth();

  }

  return super.getWidth();

 }

 public void addGroup(Group group) {

  groups.add(group);

  int row = group.getRow();

  int rowSpan = group.getRowSpan();

  rowCount = Math.max(rowCount, row + rowSpan);

  int column = group.getColumn();

  int columnSpan = group.getColumnSpan();

  columnCount = Math.max(columnCount, column +

columnSpan);

 }

 public void removeAllGroups() {

  groups.clear();

 }

 public List<Group> getGroups() {

  List<Group> list = new ArrayList<Group>();

  list.addAll(groups);

  return list;

 }

 public List<Group> getGroupsAtColumn(int columnIndex) {

  List<Group> list = new ArrayList<Group>();

  for (Group group : groups) {

   int minColumnIndex = group.getColumn();

   int maxColumnIndex = minColumnIndex +

group.getColumnSpan() -

   1;

   if (minColumnIndex <= columnIndex &&

maxColumnIndex >=

   columnIndex) {

    list.add(group);

   }

  }

  return list;

 }

 public List<Group> getGroupsAtRow(int rowIndex) {

  List<Group> list = new ArrayList<Group>();

  for (Group group : groups) {

   int minRowIndex = group.getRow();

   int maxRowIndex = minRowIndex +

group.getRowSpan() - 1;

   if (minRowIndex <= rowIndex && maxRowIndex

>= rowIndex) {

    list.add(group);

   }

  }

  return list;

 }

 public int getRowCount() {

  return this.rowCount;

 }

 public int getColumnCount() {

  return this.columnCount;

 }

 @Override

 public void setTable(JTable table) {

  super.setColumnModel(table.getColumnModel());

  super.setTable(table);

 }

 public Group getGroup(int row, int column) {

  for (Group group : groups) {

   int rowIndex = group.getRow();

   int columnIndex = group.getColumn();

   int rowSpan = group.getRowSpan();

   int columnSpan = group.getColumnSpan();

   if (rowIndex <= row && rowIndex + rowSpan >

row &&

   columnIndex <= column && columnIndex +

columnSpan > column)

    return group;

  }

  return null;

 }

 @Override

 protected TableCellRenderer createDefaultRenderer() {

  return new TableHeaderRenderer();

 }

}

常量类:

package jtble;

public class Constants {

 static int TABLE_ROW_HEIGHT = 20;

}

里面用到的TableHeaderRenderer, 没什么花头的, 贴出来看看

package jtble;

import java.awt.Color;

import java.awt.Component;

import java.awt.Dimension;

import java.awt.Rectangle;

import java.io.Serializable;

import javax.swing.JLabel;

import javax.swing.JTable;

import javax.swing.UIManager;

import javax.swing.table.DefaultTableCellRenderer;

import javax.swing.table.JTableHeader;

import javax.swing.table.TableCellRenderer;

@SuppressWarnings("serial")

public class TableHeaderRenderer extends JLabel implements

TableCellRenderer,

  Serializable {

 public TableHeaderRenderer() {

  setOpaque(true);

  setHorizontalAlignment(JLabel.CENTER);

 }

 // implements javax.swing.table.TableCellRenderer

 public Component getTableCellRendererComponent(JTable table,

Object value,

   boolean isSelected, boolean hasFocus, int row,

int column) {

  if (table != null) {

   JTableHeader header = table.getTableHeader();

   if (header != null) {

    setForeground(header.getForeground

());

    setBackground(header.getBackground

());

    setFont(header.getFont());

   }

  }

  setBorder(UIManager.getBorder

("TableHeader.cellBorder"));

  setValue(value);

  Dimension dim = getPreferredSize();

  if (dim.height < Constants.TABLE_ROW_HEIGHT)

   setPreferredSize(new Dimension

(getPreferredSize().width,

Constants.TABLE_ROW_HEIGHT));

  return this;

 }

 public boolean isOpaque() {

  Color back = getBackground();

  Component p = getParent();

  if (p != null) {

   p = p.getParent();

  }

  // p should now be the JTable.

  boolean colorMatch = (back != null) && (p != null)

    && back.equals(p.getBackground()) &&

p.isOpaque();

  return !colorMatch && super.isOpaque();

 }

 public void invalidate() {

 }

 public void validate() {

 }

 public void revalidate() {

 }

 public void repaint(long tm, int x, int y, int width, int height) {

 }

 public void repaint(Rectangle r) {

 }

 public void repaint() {

 }

 protected void firePropertyChange(String propertyName, Object

oldValue,

   Object newValue) {

  // Strings get interned

  if (propertyName == "text") {

   super.firePropertyChange(propertyName,

oldValue, newValue);

  }

 }

 public void firePropertyChange(String propertyName, boolean

oldValue,

   boolean newValue) {

 }

 protected void setValue(Object value) {

  setText((value == null) ? "" : value.toString());

 }

 public static class UIResource extends DefaultTableCellRenderer

implements

   javax.swing.plaf.UIResource {

 }

}

最重要的UI登场, 哈哈

package jtble;

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 java.util.List;

import javax.swing.JComponent;

import javax.swing.plaf.basic.BasicTableHeaderUI;

import javax.swing.table.TableCellRenderer;

import javax.swing.table.TableColumn;

import javax.swing.table.TableColumnModel;

public class GroupableTableHeaderUI extends BasicTableHeaderUI {

 @Override

 public void paint(Graphics g, JComponent c) {

  if (header.getColumnModel().getColumnCount() <= 0) {

   return;

  }

  boolean ltr = header.getComponentOrientation

().isLeftToRight();

  Rectangle clip = g.getClipBounds();

  Point left = clip.getLocation();

  Point right = new Point(clip.x + clip.width - 1, clip.y);

  TableColumnModel cm = header.getColumnModel();

  int cMin = header.columnAtPoint(ltr ? left : right);

  int cMax = header.columnAtPoint(ltr ? right : left);

  // 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 = cm.getColumnCount() - 1;

  }

  // TableColumn draggedColumn =

header.getDraggedColumn();

  int columnWidth;

  // Rectangle cellRect = header.getHeaderRect(ltr ? cMin :

cMax);

  TableColumn aColumn;

  // if (ltr) {

  // for (int column = cMin; column <= cMax; column++) {

  // aColumn = cm.getColumn(column);

  // columnWidth = aColumn.getWidth();

  // cellRect.width = columnWidth;

  // // if (aColumn != draggedColumn) {

  // paintCell(g, cellRect, column);

  // // }

  // cellRect.x += columnWidth;

  // }

  // } else {

  // for (int column = cMax; column >= cMin; column--) {

  // aColumn = cm.getColumn(column);

  // columnWidth = aColumn.getWidth();

  // cellRect.width = columnWidth;

  // // if (aColumn != draggedColumn) {

  // paintCell(g, cellRect, column);

  // // }

  // cellRect.x += columnWidth;

  // }

  // }

  GroupableTableHeader gHeader =

(GroupableTableHeader) header;

  for (int row = 0, rowCount = gHeader.getRowCount(); row

< rowCount; row++) {

   Rectangle cellRect = gHeader.getHeaderRect

(row, ltr ? cMin : cMax);

   if (ltr) {

    for (int column = cMin; column <=

cMax; column++) {

     Group group =

gHeader.getGroup(row, column);

     cellRect.width = 0;

     for (int from =

group.getColumn(), to = from

       +

group.getColumnSpan() - 1; from <= to; from++) {

      aColumn =

cm.getColumn(from);

      columnWidth =

aColumn.getWidth();

      cellRect.width +=

columnWidth;

     }

     cellRect.y =

gHeader.getYOfGroup(group);

     cellRect.height =

gHeader.getHeightOfGroup(group);

     paintCell(g, cellRect, row,

column);

     cellRect.x += cellRect.width;

     column +=

group.getColumnSpan() - 1;

    }

   } else {

    for (int column = cMax; column >=

cMin; column--) {

     Group group =

gHeader.getGroup(row, column);

     cellRect.width = 0;

     for (int from =

group.getColumn(), to = from

       +

group.getColumnSpan() - 1; from <= to; from++) {

      aColumn =

cm.getColumn(from);

      columnWidth =

aColumn.getWidth();

      cellRect.width +=

columnWidth;

     }

     paintCell(g, cellRect, row,

column);

     cellRect.x += cellRect.width;

     column -=

group.getColumnSpan() - 1;

    }

   }

  }

  // Remove all components in the rendererPane.

  rendererPane.removeAll();

 }

 private void paintCell(Graphics g, Rectangle cellRect, int rowIndex,

   int columnIndex) {

  Component component = getHeaderRenderer(rowIndex,

columnIndex);

  rendererPane.paintComponent(g, component, header,

cellRect.x,

    cellRect.y, cellRect.width,

cellRect.height, true);

 }

 private Component getHeaderRenderer(int rowIndex, int

columnIndex) {

  GroupableTableHeader gHeader =

(GroupableTableHeader) header;

  Group group = gHeader.getGroup(rowIndex,

columnIndex);

  TableCellRenderer renderer = header.getDefaultRenderer

();

  return renderer.getTableCellRendererComponent

(header.getTable(), group

    .getHeaderValue(), false, false, -1,

columnIndex);

 }

 private int getHeaderHeight() {

  int height = 0;

  int tempHeight = 0;

  GroupableTableHeader gHeader =

(GroupableTableHeader) header;

  TableColumnModel cm = header.getColumnModel();

  for (int column = 0, columnCount = cm.getColumnCount();

column < columnCount; column++) {

   tempHeight = 0;

   List<Group> groups =

gHeader.getGroupsAtColumn(column);

   for (Group group : groups) {

    TableCellRenderer renderer =

gHeader.getDefaultRenderer();

    Component comp =

renderer.getTableCellRendererComponent(header

      .getTable(),

group.getHeaderValue(), false, false, -1,

      column);

    int rendererHeight =

comp.getPreferredSize().height;

    tempHeight += rendererHeight;

   }

   height = Math.max(height, tempHeight);

  }

  return height;

 }

 private Dimension createHeaderSize(long width) {

  // TableColumnModel columnModel =

header.getColumnModel();

  // None of the callers include the intercell spacing, do it

here.

  if (width > Integer.MAX_VALUE) {

   width = Integer.MAX_VALUE;

  }

  return new Dimension((int) width, getHeaderHeight());

 }

 public Dimension getMinimumSize(JComponent c) {

  long width = 0;

  Enumeration enumeration = header.getColumnModel

().getColumns();

  while (enumeration.hasMoreElements()) {

   TableColumn aColumn = (TableColumn)

enumeration.nextElement();

   width = width + aColumn.getMinWidth();

  }

  return createHeaderSize(width);

 }

 public Dimension getPreferredSize(JComponent c) {

  long width = 0;

  Enumeration enumeration = header.getColumnModel

().getColumns();

  while (enumeration.hasMoreElements()) {

   TableColumn aColumn = (TableColumn)

enumeration.nextElement();

   width = width + aColumn.getPreferredWidth();

  }

  return createHeaderSize(width);

 }

 public Dimension getMaximumSize(JComponent c) {

  long width = 0;

  Enumeration enumeration = header.getColumnModel

().getColumns();

  while (enumeration.hasMoreElements()) {

   TableColumn aColumn = (TableColumn)

enumeration.nextElement();

   width = width + aColumn.getMaxWidth();

  }

  return createHeaderSize(width);

 }

}

最后顺便贴一个测试程序, 可以看看怎么用法. 文档我也没有写过

package jtble;

import java.awt.BorderLayout;

import java.awt.HeadlessException;

import javax.swing.JFrame;

import javax.swing.JScrollPane;

import javax.swing.JTable;

import javax.swing.table.DefaultTableModel;

@SuppressWarnings("serial")

public class Test extends JFrame {

 public static void main(String[] args) {

  Test test = new Test();

  test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

  test.setSize(800, 600);

  test.setVisible(true);

 }

 private DefaultTableModel tableModel = new DefaultTableModel() {

  @Override

  public int getColumnCount() {

   return 6;

  }

  @Override

  public int getRowCount() {

   return 2;

  }

 };

 private JTable table = new JTable(tableModel);

 private JScrollPane scroll = new JScrollPane(table);

 public Test() throws HeadlessException {

  table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

  GroupableTableHeader tableHeader = new

GroupableTableHeader();

  table.setTableHeader(tableHeader);

  DefaultGroup group = new DefaultGroup();

  group.setRow(0);

  group.setRowSpan(2);

  group.setColumn(0);

  group.setHeaderValue("楼层");

  tableHeader.addGroup(group);

  group = new DefaultGroup();

  group.setRow(0);

  group.setRowSpan(2);

  group.setColumn(1);

  group.setHeaderValue("水平/垂直系数");

  tableHeader.addGroup(group);

  group = new DefaultGroup();

  group.setRow(0);

  group.setColumn(2);

  group.setColumnSpan(2);

  group.setHeaderValue("A & B");

  tableHeader.addGroup(group);

  group = new DefaultGroup();

  group.setRow(1);

  group.setColumn(2);

  group.setHeaderValue("Column A");

  tableHeader.addGroup(group);

  group = new DefaultGroup();

  group.setRow(1);

  group.setColumn(3);

  group.setHeaderValue("Column B");

  tableHeader.addGroup(group);

  group = new DefaultGroup();

  group.setRow(0);

  group.setColumn(4);

  group.setColumnSpan(2);

  group.setHeaderValue("C & D");

  tableHeader.addGroup(group);

  group = new DefaultGroup();

  group.setRow(1);

  group.setColumn(4);

  group.setHeaderValue("Column C");

  tableHeader.addGroup(group);

  group = new DefaultGroup();

  group.setRow(1);

  group.setColumn(5);

  group.setHeaderValue("Column D");

  tableHeader.addGroup(group);

  getContentPane().add(scroll, BorderLayout.CENTER);

 }

}