Skip to Main Content

Java SE (Java Platform, Standard Edition)

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

Nested sub-header (Groupable Header) JTable Example and JDK 1.5

843804Mar 16 2005 — edited Oct 17 2008
There is an old Nobuo Tamemasa example of making a JTable with grouped column headers at:
http://www.codeguru.com/java/articles/124.shtml

I made a couple of minor mods to get it to run under JDK 1.4. It works like a charm. If I run the same code under JDK 1.5.1, only the lowest level column headers are painted.

Has anyone noticed this and come up with a fix?

Here are the 4 classes (with my minor mods) required to run the test...
package GroupableColumnTable;
//File: ColumnGroup.java
/*
 * (swing1.1beta3)
 * 
 */


import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;


/**
  * ColumnGroup
  *
  * @version 1.0 10/20/98
  * @author Nobuo Tamemasa
  */
 
public class ColumnGroup {
  protected TableCellRenderer renderer;
  protected Vector v;
  protected String text;
  protected int margin=0;

  public ColumnGroup(String text) {
	this(null,text);
  }

  public ColumnGroup(TableCellRenderer renderer,String text) {
	if (renderer == null) {
	  this.renderer = new DefaultTableCellRenderer() {
	    public Component getTableCellRendererComponent(JTable table, Object value,
			     boolean isSelected, boolean hasFocus, int row, int column) {
	      JTableHeader header = table.getTableHeader();
	      if (header != null) {
		setForeground(header.getForeground());
		setBackground(header.getBackground());
		setFont(header.getFont());
	      }
	      setHorizontalAlignment(JLabel.CENTER);
	      setText((value == null) ? "" : value.toString());
	      setBorder(UIManager.getBorder("TableHeader.cellBorder"));
	      return this;
	    }
	  };
	} else {
	  this.renderer = renderer;
	}
	this.text = text;
	v = new Vector();
  }

  
  /**
   * @param obj    TableColumn or ColumnGroup
   */
  public void add(Object obj) {
	if (obj == null) { return; }
	v.addElement(obj);
  }

  
  /**
   * @param c    TableColumn
   * @param v    ColumnGroups
   */
  public Vector getColumnGroups(TableColumn c, Vector g) {
	g.addElement(this);
	if (v.contains(c)) return g;	
	Enumeration enum = v.elements();
	while (enum.hasMoreElements()) {
	  Object obj = enum.nextElement();
	  if (obj instanceof ColumnGroup) {
	    Vector groups = 
	      (Vector)((ColumnGroup)obj).getColumnGroups(c,(Vector)g.clone());
	    if (groups != null) return groups;
	  }
	}
	return null;
  }
	
  public TableCellRenderer getHeaderRenderer() {
	return renderer;
  }
	
  public void setHeaderRenderer(TableCellRenderer renderer) {
	if (renderer != null) {
	  this.renderer = renderer;
	}
  }
	
  public Object getHeaderValue() {
	return text;
  }
  
  public Dimension getSize(JTable table) {
	Component comp = renderer.getTableCellRendererComponent(
	    table, getHeaderValue(), false, false,-1, -1);
	int height = comp.getPreferredSize().height; 
	int width  = 0;
	Enumeration enum = v.elements();
	while (enum.hasMoreElements()) {
	  Object obj = enum.nextElement();
	  if (obj instanceof TableColumn) {
	    TableColumn aColumn = (TableColumn)obj;
	    width += aColumn.getWidth();
	    width += margin;
	  } else {
	    width += ((ColumnGroup)obj).getSize(table).width;
	  }
	}
	return new Dimension(width, height);
  }

  public void setColumnMargin(int margin) {
	this.margin = margin;
	Enumeration enum = v.elements();
	while (enum.hasMoreElements()) {
	  Object obj = enum.nextElement();
	  if (obj instanceof ColumnGroup) {
	    ((ColumnGroup)obj).setColumnMargin(margin);
	  }
	}
  }
}


package GroupableColumnTable;

//File: GroupableHeaderExample.java
//
/* (swing1.1beta3)
 *
 * |-----------------------------------------------------|
 * |	|	Name	  |	    Language	     |
 * |	|-----------------|--------------------------|
 * |  SNo.	|	 |	  |	   |	  Others     |
 * |	|   1	 |    2   | Native |-----------------|
 * |	|	 |	  |	   |   2    |	3    |	
 * |-----------------------------------------------------|
 * |	|	 |	  |	   |	    |	     |
 *
 */
//package jp.gr.java_conf.tame.swing.examples;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

 
/**
 * @version 1.0 11/09/98
 */
public class GroupableHeaderExample extends JFrame {

  GroupableHeaderExample() {
	super( "Groupable Header Example" );

    DefaultTableModel dm = new DefaultTableModel();
	dm.setDataVector(new Object[][]{
	  {"119","foo","bar","ja","ko","zh"},
	  {"911","bar","foo","en","fr","pt"}},
	new
Object[]{"SNo.","1","2","Native","2","3"});

    JTable table = new JTable( dm ) {
	  protected JTableHeader createDefaultTableHeader() {
	    return new GroupableTableHeader(columnModel);
	  }
	};
	TableColumnModel cm = table.getColumnModel();
	ColumnGroup g_name = new ColumnGroup("Name");
	g_name.add(cm.getColumn(1));
	g_name.add(cm.getColumn(2));
	ColumnGroup g_lang = new ColumnGroup("Language");
	g_lang.add(cm.getColumn(3));
	ColumnGroup g_other = new ColumnGroup("Others");
	g_other.add(cm.getColumn(4));
	g_other.add(cm.getColumn(5));
	g_lang.add(g_other);
	GroupableTableHeader header = (GroupableTableHeader)table.getTableHeader();
	header.addColumnGroup(g_name);
	header.addColumnGroup(g_lang);
	JScrollPane scroll = new JScrollPane( table );
	getContentPane().add( scroll );
	setSize( 400, 120 );   
  }

  public static void main(String[] args) {
	GroupableHeaderExample frame = new GroupableHeaderExample();
	frame.addWindowListener( new WindowAdapter() {
	  public void windowClosing( WindowEvent e ) {
	    System.exit(0);
	  }
	});
	frame.setVisible(true);
  }
}

package GroupableColumnTable;

//File: GroupableTableHeader.java
//
/*
 * (swing1.1beta3)
 * 
 */


import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

 

/**
  * GroupableTableHeader
  *
  * @version 1.0 10/20/98
  * @author Nobuo Tamemasa
  */

public class GroupableTableHeader extends JTableHeader {
  private static final String uiClassID = "GroupableTableHeaderUI";
  protected Vector columnGroups = null;
	
  public GroupableTableHeader(TableColumnModel model) {
	super(model);
	setUI(new GroupableTableHeaderUI());
	setReorderingAllowed(false);
  }
  
  public void setReorderingAllowed(boolean b) {
	reorderingAllowed = false;
  }
	
  public void addColumnGroup(ColumnGroup g) {
	if (columnGroups == null) {
	  columnGroups = new Vector();
	}
	columnGroups.addElement(g);
  }

  public Enumeration getColumnGroups(TableColumn col) {
	if (columnGroups == null) return null;
	Enumeration enum = columnGroups.elements();
	while (enum.hasMoreElements()) {
	  ColumnGroup cGroup = (ColumnGroup)enum.nextElement();
	  Vector v_ret = (Vector)cGroup.getColumnGroups(col,new Vector());
	  if (v_ret != null) { 
	    return v_ret.elements();
	  }
	}
	return null;
  }
  
  public void setColumnMargin() {
	if (columnGroups == null) return;
	int columnMargin = getColumnModel().getColumnMargin();
	Enumeration enum = columnGroups.elements();
	while (enum.hasMoreElements()) {
	  ColumnGroup cGroup = (ColumnGroup)enum.nextElement();
	  cGroup.setColumnMargin(columnMargin);
	}
  }
  
}

package GroupableColumnTable;

//File: GroupableTableHeaderUI.java
//
/*
 * (swing1.1beta3)
 * 
 */



import java.util.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.plaf.basic.*;



public class GroupableTableHeaderUI extends BasicTableHeaderUI {
  
  public void paint(Graphics g, JComponent c) {
	Rectangle clipBounds = g.getClipBounds();
	if (header.getColumnModel() == null) return;
	((GroupableTableHeader)header).setColumnMargin();
	int column = 0;
	Dimension size = header.getSize();
	Rectangle cellRect  = new Rectangle(0, 0, size.width, size.height);
	Hashtable h = new Hashtable();
	int columnMargin = header.getColumnModel().getColumnMargin();
	
	Enumeration enumeration = header.getColumnModel().getColumns();
	while (enumeration.hasMoreElements()) {
	  cellRect.height = size.height;
	  cellRect.y	  = 0;
	  TableColumn aColumn = (TableColumn)enumeration.nextElement();
	  Enumeration cGroups = ((GroupableTableHeader)header).getColumnGroups(aColumn);
	  if (cGroups != null) {
	    int groupHeight = 0;
	    while (cGroups.hasMoreElements()) {
	      ColumnGroup cGroup = (ColumnGroup)cGroups.nextElement();
	      Rectangle groupRect = (Rectangle)h.get(cGroup);
	      if (groupRect == null) {
		groupRect = new Rectangle(cellRect);
		Dimension d = cGroup.getSize(header.getTable());
		groupRect.width  = d.width;
		groupRect.height = d.height;	
		h.put(cGroup, groupRect);
	      }
	      paintCell(g, groupRect, cGroup);
	      groupHeight += groupRect.height;
	      cellRect.height = size.height - groupHeight;
	      cellRect.y      = groupHeight;
	    }
	  }	 
	  cellRect.width = aColumn.getWidth() + columnMargin;
	  if (cellRect.intersects(clipBounds)) {
	    paintCell(g, cellRect, column);
	  }
	  cellRect.x += cellRect.width;
	  column++;
	}
  }

  private void paintCell(Graphics g, Rectangle cellRect, int columnIndex) {
	TableColumn aColumn = header.getColumnModel().getColumn(columnIndex);
	TableCellRenderer renderer = header.getDefaultRenderer ();
	Component component = renderer.getTableCellRendererComponent(
	  header.getTable(), aColumn.getHeaderValue(),false, false, -1, columnIndex);
	rendererPane.add(component);
	rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y,
				    cellRect.width, cellRect.height, true);
  }

  private void paintCell(Graphics g, Rectangle cellRect,ColumnGroup cGroup) {
	TableCellRenderer renderer = cGroup.getHeaderRenderer();
	Component component = renderer.getTableCellRendererComponent(
	  header.getTable(), cGroup.getHeaderValue(),false, false, -1, -1);
	rendererPane.add(component);
	rendererPane.paintComponent(g, component, header, cellRect.x, cellRect.y,
				    cellRect.width, cellRect.height, true);
  }

  private int getHeaderHeight() {
	int height = 0;
	TableColumnModel columnModel = header.getColumnModel();
	for(int column = 0; column < columnModel.getColumnCount(); column++) {
	  TableColumn aColumn = columnModel.getColumn(column);
	  TableCellRenderer renderer = header.getDefaultRenderer();
	  Component comp = renderer.getTableCellRendererComponent(
	    header.getTable(), aColumn.getHeaderValue(), false, false,-1, column);
	  int cHeight = comp.getPreferredSize().height;
	  Enumeration enum = ((GroupableTableHeader)header).getColumnGroups(aColumn);	   
	  if (enum != null) {
	    while (enum.hasMoreElements()) {
	      ColumnGroup cGroup = (ColumnGroup)enum.nextElement();
	      cHeight += cGroup.getSize(header.getTable()).height;
	    }
	  }
	  height = Math.max(height, cHeight);
	}
	return height;
  }

  private Dimension createHeaderSize(long width) {
	TableColumnModel columnModel = header.getColumnModel();
	width += columnModel.getColumnMargin() * columnModel.getColumnCount();
	if (width > Integer.MAX_VALUE) {
	  width = Integer.MAX_VALUE;
	}
	return new Dimension((int)width, getHeaderHeight());
  }

  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);
  }
}
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Nov 14 2008
Added on Mar 16 2005
28 comments
2,348 views