groupable + multiline table header paint problem

hi, i try to make a groupable + multiline table header

based on Nobuo Tamesama's code...

there are some problems which i considered tolerable except one...

the header didn't paint correctly when i set the autoResizeMode into autoresizemode_off

and resize the columns pass the scrollpane width...

thx in advance

here's the complete code :

import java.io.*;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.swing.table.*;

import java.util.*;

import javax.swing.border.*;

import javax.swing.plaf.basic.*;

publicclass GroupableHeaderExampleextends JFrame{

GroupableHeaderExample(){

super("Groupable Header Example");

JScrollPane sp =new JScrollPane();

Object[][] data ={{"b1k1","b1k2","b1k3","b1k4","b1k5"},{"b2k1","b2k2","b2k3","b2k4","b2k5"}};

JTable table =new JTable(new DefaultTableModel(data,new Object[]{"Kol1","Kol2\nmmm","Kol3","kol4\nmmm\nnnn"," \n \nKol5\nmmm"})){

protected JTableHeader createDefaultTableHeader(){

returnnew GroupableTableHeader(columnModel);

}

};

table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

ColumnGroup cg =new ColumnGroup("CG", 0, 3);

ColumnGroup cg2 =new ColumnGroup("CG2\nmmm", 1, 3);

ColumnGroup cg3 =new ColumnGroup("CG3", 1, 2);

GroupableTableHeader header = (GroupableTableHeader)table.getTableHeader();

header.addColumnGroup(cg3);

header.addColumnGroup(cg);

header.addColumnGroup(cg2);

header.fitHeight();

sp.setViewportView(table);

getContentPane().add(sp);

setSize(400, 300);

}

publicstaticvoid main(String[] args){

GroupableHeaderExample frame =new GroupableHeaderExample();

frame.addWindowListener(new WindowAdapter(){

publicvoid windowClosing( WindowEvent e ){

System.exit(0);

}

});

frame.setVisible(true);

}

}

class GroupableTableHeaderextends JTableHeader{

private Vector<ColumnGroup> columnGroups =new Vector<ColumnGroup>(1, 1);

public GroupableTableHeader(TableColumnModel model){

super(model);

setUI(new GroupableTableHeaderUI());

setReorderingAllowed(false);

}

publicvoid addColumnGroup(ColumnGroup cg){

if(columnGroups.size() == 0){

columnGroups.addElement(cg);

return;

}

int size = columnGroups.size();

for(int i = 0; i < size; i++){

if(cg.getLength() > ((ColumnGroup)columnGroups.elementAt(i)).getLength())

columnGroups.insertElementAt(cg, i);

else{

if(i == size - 1)

columnGroups.addElement(cg);

}

}

}

publicvoid fitHeight(){

int[] counter =newint[getTable().getColumnCount()];

for(int i = 0; i < getTable().getColumnCount(); i++){

int level = 0;

for(int j = 0; j < columnGroups.size(); j++){

if(i >= ((ColumnGroup)columnGroups.elementAt(j)).getStartIndex() && i <= ((ColumnGroup)columnGroups.elementAt(j)).getEndIndex())

level = level + getNewLineCount(((ColumnGroup)columnGroups.elementAt(j)).getText());

}

counter[i] = level + getNewLineCount(table.getColumnModel().getColumn(i).getHeaderValue().toString());

}

int maxCounter = counter[0];

for(int i = 0; i < counter.length; i++){

if(counter[i] > maxCounter)

maxCounter = counter[i];

}

setPreferredSize(new Dimension(100, (maxCounter) * 20));

}

public Vector getColumnGroups(){

return columnGroups;

}

publicint getNewLineCount(String str){

BufferedReader br =new BufferedReader(new StringReader(str));

String line;

Vector<String> v =new Vector<String>(1, 1);

try{

while((line = br.readLine()) !=null){

v.addElement(line);

}

}

catch(IOException ex){

JOptionPane.showMessageDialog(null, ex.getMessage(),"Informasi", JOptionPane.INFORMATION_MESSAGE);

System.exit(0);

}

int i = 0;

boolean b =false;

for(i = 0; i < v.size(); i++){

for(int j = 0; j < v.elementAt(i).length(); j++){

if(v.elementAt(i).charAt(j) !=' '){

b =true;

break;

}

}

if(b)

break;

}

if(i == v.size())

i = 0;

return v.size() - i;

}

publicvoid updateUI(){

setUI(new GroupableTableHeaderUI());

}

}

class GroupableTableHeaderUIextends BasicTableHeaderUI{

publicvoid paint(Graphics g, JComponent c){

TableCellRenderer renderer =new MultiLineHeaderRendererEx();

Component[] cmp =new Component[header.getColumnModel().getColumnCount()];

Vector cg = ((GroupableTableHeader)header).getColumnGroups();

Component[] cmpGroup =new Component[cg.size()];

TableColumnModel tcm = header.getTable().getColumnModel();

for(int i = 0; i < cmpGroup.length; i++){

cmpGroup[i] = renderer.getTableCellRendererComponent(header.getTable(), ((ColumnGroup)cg.elementAt(i)).getText(), false, false, -1, i);

rendererPane.add(cmpGroup[i]);

int x = 0;

int y = 0;

int height = 20 * ((GroupableTableHeader)header).getNewLineCount(((ColumnGroup)cg.elementAt(i)).getText());

for(int j = 0; j < ((ColumnGroup)cg.elementAt(i)).getStartIndex(); j++)

x += tcm.getColumn(j).getWidth();

for(int j = 0; j < cmpGroup.length; j++){

if(i == j)

continue;

if(((ColumnGroup)cg.elementAt(i)).getStartIndex() >= ((ColumnGroup)cg.elementAt(j)).getStartIndex() && ((ColumnGroup)cg.elementAt(i)).getEndIndex() <= ((ColumnGroup)cg.elementAt(j)).getEndIndex())

y = ((ColumnGroup)cg.elementAt(j)).getY() + ((ColumnGroup)cg.elementAt(j)).getHeight();

}

((ColumnGroup)cg.elementAt(i)).setY(y);

((ColumnGroup)cg.elementAt(i)).setHeight(height);

int width = 0;

for(int j = ((ColumnGroup)cg.elementAt(i)).getStartIndex(); j <= ((ColumnGroup)cg.elementAt(i)).getEndIndex(); j++)

width += tcm.getColumn(j).getWidth();

rendererPane.add(cmpGroup[i]);

rendererPane.paintComponent(g, cmpGroup[i], header, x, y, width, height,true);

}

for(int i = 0; i < cmp.length; i++){

cmp[i] = renderer.getTableCellRendererComponent(header.getTable(), header.getColumnModel().getColumn(i).getHeaderValue(), false, false, -1, i);

rendererPane.add(cmp[i]);

int x = 0;

int y = 0;

for(int j = 0; j < i; j++)

x += tcm.getColumn(j).getWidth();

for(int j = 0; j < cmpGroup.length; j++){

if(i >= ((ColumnGroup)cg.elementAt(j)).getStartIndex() && i <= ((ColumnGroup)cg.elementAt(j)).getEndIndex())

y = ((ColumnGroup)cg.elementAt(j)).getY() + ((ColumnGroup)cg.elementAt(j)).getHeight();

}

rendererPane.add(cmp[i]);

rendererPane.paintComponent(g, cmp[i], header, x, y, tcm.getColumn(i).getWidth(), (header.getPreferredSize().height - y),true);

}

}

}

class MultiLineHeaderRendererExextends JListimplements TableCellRenderer{

public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected,boolean hasFocus,int row,int col){

if(((GroupableTableHeader)table.getTableHeader()).getNewLineCount(value.toString()) == 1){

JLabel header =new JLabel();

header.setForeground(table.getTableHeader().getForeground());

header.setBackground(table.getTableHeader().getBackground());

header.setFont(table.getTableHeader().getFont());

header.setHorizontalAlignment(JLabel.CENTER);

header.setText(value.toString());

header.setBorder(UIManager.getBorder("TableHeader.cellBorder"));

return header;

}

else{

setOpaque(true);

setForeground(UIManager.getColor("TableHeader.foreground"));

setBackground(UIManager.getColor("TableHeader.background"));

setBorder(UIManager.getBorder("TableHeader.cellBorder"));

setFont(UIManager.getFont("TableHeader.font"));

ListCellRenderer renderer = getCellRenderer();

((JLabel)renderer).setHorizontalAlignment(SwingConstants.CENTER);

setCellRenderer(renderer);

String str = value.toString();

BufferedReader br =new BufferedReader(new StringReader(str));

String line;

Vector<String> v =new Vector<String>(1, 1);

try{

while((line = br.readLine()) !=null){

v.addElement(line);

}

}

catch(IOException ex){

JOptionPane.showMessageDialog(null, ex.getMessage(),"Informasi", JOptionPane.INFORMATION_MESSAGE);

System.exit(0);

}

setListData(v);

returnthis;

}

}

}

[16610 byte] By [shy_guya] at [2007-10-3 4:25:07]
# 1
i'm using jdk1.5.0_02
shy_guya at 2007-7-14 22:27:37 > top of Java-index,Desktop,Core GUI APIs...
# 2

OMG ! the code i posted before is incomplete

sorry...

here's the complete one, pls help :

import java.io.*;

import java.awt.*;

import java.awt.event.*;

import javax.swing.*;

import javax.swing.table.*;

import java.util.*;

import javax.swing.border.*;

import javax.swing.plaf.basic.*;

public class GroupableHeaderExample extends JFrame {

GroupableHeaderExample() {

super("Groupable Header Example");

JScrollPane sp = new JScrollPane();

Object[][] data = {{"b1k1", "b1k2", "b1k3", "b1k4", "b1k5"}, {"b2k1", "b2k2", "b2k3", "b2k4", "b2k5"}};

JTable table = new JTable(new DefaultTableModel(data, new Object[]{"Kol1", "Kol2\nmmm", "Kol3", "kol4\nmmm\nnnn", "Kol5\nmmm"})) {

protected JTableHeader createDefaultTableHeader() {

return new GroupableTableHeader(columnModel);

}

};

table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

ColumnGroup cg = new ColumnGroup("CG", 0, 4);

ColumnGroup cg2 = new ColumnGroup("CG2\nmmm", 1, 4);

ColumnGroup cg3 = new ColumnGroup("CG3", 1, 2);

ColumnGroup cg4 = new ColumnGroup("CG4", 3, 4);

GroupableTableHeader header = (GroupableTableHeader)table.getTableHeader();

header.addColumnGroup(cg4);

header.addColumnGroup(cg2);

header.addColumnGroup(cg3);

header.addColumnGroup(cg);

header.fitHeight();

sp.setViewportView(table);

getContentPane().add(sp);

setSize(400, 300);

}

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);

}

}

class GroupableTableHeader extends JTableHeader {

private Vector<ColumnGroup> columnGroups = new Vector<ColumnGroup>(1, 1);

public GroupableTableHeader(TableColumnModel model) {

super(model);

setUI(new GroupableTableHeaderUI());

setReorderingAllowed(false);

}

public void addColumnGroup(ColumnGroup cg) {

if(columnGroups.size() == 0) {

columnGroups.addElement(cg);

return;

}

int size = columnGroups.size();

for(int i = 0; i < size; i++) {

if(cg.getLength() > ((ColumnGroup)columnGroups.elementAt(i)).getLength()) {

columnGroups.insertElementAt(cg, i);

break;

}

else {

if(i == size - 1)

columnGroups.addElement(cg);

}

}

}

public void fitHeight() {

int[] counter = new int[getTable().getColumnCount()];

for(int i = 0; i < getTable().getColumnCount(); i++) {

int level = 0;

for(int j = 0; j < columnGroups.size(); j++) {

if(i >= ((ColumnGroup)columnGroups.elementAt(j)).getStartIndex() && i <= ((ColumnGroup)columnGroups.elementAt(j)).getEndIndex())

level = level + getNewLineCount(((ColumnGroup)columnGroups.elementAt(j)).getText());

}

counter[i] = level + getNewLineCount(table.getColumnModel().getColumn(i).getHeaderValue().toString());

}

int maxCounter = counter[0];

for(int i = 0; i < counter.length; i++) {

if(counter[i] > maxCounter)

maxCounter = counter[i];

}

setPreferredSize(new Dimension(100, (maxCounter) * 20));

}

public Vector getColumnGroups() {

return columnGroups;

}

public int getNewLineCount(String str) {

BufferedReader br = new BufferedReader(new StringReader(str));

String line;

Vector<String> v = new Vector<String>(1, 1);

try {

while((line = br.readLine()) != null) {

v.addElement(line);

}

}

catch(IOException ex) {

JOptionPane.showMessageDialog(null, ex.getMessage(), "Informasi", JOptionPane.INFORMATION_MESSAGE);

System.exit(0);

}

int i = 0;

boolean b = false;

for(i = 0; i < v.size(); i++) {

for(int j = 0; j < v.elementAt(i).length(); j++) {

if(v.elementAt(i).charAt(j) != ' ') {

b = true;

break;

}

}

if(b)

break;

}

if(i == v.size())

i = 0;

return v.size() - i;

}

public void updateUI(){

setUI(new GroupableTableHeaderUI());

}

}

class GroupableTableHeaderUI extends BasicTableHeaderUI {

public void paint(Graphics g, JComponent c) {

TableCellRenderer renderer = new MultiLineHeaderRendererEx();

Component[] cmp = new Component[header.getColumnModel().getColumnCount()];

Vector cg = ((GroupableTableHeader)header).getColumnGroups();

Component[] cmpGroup = new Component[cg.size()];

TableColumnModel tcm = header.getTable().getColumnModel();

for(int i = 0; i < cmpGroup.length; i++) {

cmpGroup[i] = renderer.getTableCellRendererComponent(header.getTable(), ((ColumnGroup)cg.elementAt(i)).getText(), false, false, -1, i);

int x = 0;

int y = 0;

int height = 20 * ((GroupableTableHeader)header).getNewLineCount(((ColumnGroup)cg.elementAt(i)).getText());

for(int j = 0; j < ((ColumnGroup)cg.elementAt(i)).getStartIndex(); j++)

x += tcm.getColumn(j).getWidth();

for(int j = 0; j < cmpGroup.length; j++) {

if(i == j)

continue;

if(((ColumnGroup)cg.elementAt(i)).getStartIndex() >= ((ColumnGroup)cg.elementAt(j)).getStartIndex() && ((ColumnGroup)cg.elementAt(i)).getEndIndex() <= ((ColumnGroup)cg.elementAt(j)).getEndIndex())

y = ((ColumnGroup)cg.elementAt(j)).getY() + ((ColumnGroup)cg.elementAt(j)).getHeight();

}

((ColumnGroup)cg.elementAt(i)).setY(y);

((ColumnGroup)cg.elementAt(i)).setHeight(height);

int width = 0;

for(int j = ((ColumnGroup)cg.elementAt(i)).getStartIndex(); j <= ((ColumnGroup)cg.elementAt(i)).getEndIndex(); j++)

width += tcm.getColumn(j).getWidth();

rendererPane.add(cmpGroup[i]);

rendererPane.paintComponent(g, cmpGroup[i], header, x, y, width, height, true);

}

for(int i = 0; i < cmp.length; i++) {

cmp[i] = renderer.getTableCellRendererComponent(header.getTable(), header.getColumnModel().getColumn(i).getHeaderValue(), false, false, -1, i);

int x = 0;

int y = 0;

for(int j = 0; j < i; j++)

x += tcm.getColumn(j).getWidth();

for(int j = 0; j < cmpGroup.length; j++) {

if(i >= ((ColumnGroup)cg.elementAt(j)).getStartIndex() && i <= ((ColumnGroup)cg.elementAt(j)).getEndIndex())

y = ((ColumnGroup)cg.elementAt(j)).getY() + ((ColumnGroup)cg.elementAt(j)).getHeight();

}

rendererPane.add(cmp[i]);

rendererPane.paintComponent(g, cmp[i], header, x, y, tcm.getColumn(i).getWidth(), (header.getPreferredSize().height - y), true);

}

}

}

class MultiLineHeaderRendererEx extends JList implements TableCellRenderer {

public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {

if(((GroupableTableHeader)table.getTableHeader()).getNewLineCount(value.toString()) == 1) {

JLabel header = new JLabel();

header.setForeground(table.getTableHeader().getForeground());

header.setBackground(table.getTableHeader().getBackground());

header.setFont(table.getTableHeader().getFont());

header.setHorizontalAlignment(JLabel.CENTER);

header.setText(value.toString());

header.setBorder(UIManager.getBorder("TableHeader.cellBorder"));

return header;

}

else {

setOpaque(true);

setForeground(UIManager.getColor("TableHeader.foreground"));

setBackground(UIManager.getColor("TableHeader.background"));

setBorder(UIManager.getBorder("TableHeader.cellBorder"));

setFont(UIManager.getFont("TableHeader.font"));

ListCellRenderer renderer = getCellRenderer();

((JLabel)renderer).setHorizontalAlignment(SwingConstants.CENTER);

setCellRenderer(renderer);

String str = value.toString();

BufferedReader br = new BufferedReader(new StringReader(str));

String line;

Vector<String> v = new Vector<String>(1, 1);

try {

while((line = br.readLine()) != null) {

v.addElement(line);

}

}

catch(IOException ex) {

JOptionPane.showMessageDialog(null, ex.getMessage(), "Informasi", JOptionPane.INFORMATION_MESSAGE);

System.exit(0);

}

setListData(v);

return this;

}

}

}

class ColumnGroup {

private String text;

private int startIndex, endIndex, y, height;

public ColumnGroup(String text, int startIndex, int endIndex) {

this.text = text;

this.startIndex = startIndex;

this.endIndex = endIndex;

}

public int getEndIndex() {

return endIndex;

}

public int getHeight() {

return height;

}

public int getLength() {

return endIndex - startIndex;

}

public int getStartIndex() {

return startIndex;

}

public String getText() {

return text;

}

public int getY() {

return y;

}

public void setHeight(int height) {

this.height = height;

}

public void setY(int y) {

this.y = y;

}

}

shy_guya at 2007-7-14 22:27:37 > top of Java-index,Desktop,Core GUI APIs...
# 3
well, it compiles and runs.what should happen that doesn't, or what do you have to do to create the problem.
Michael_Dunna at 2007-7-14 22:27:37 > top of Java-index,Desktop,Core GUI APIs...
# 4
set the table's autoResizeMode into autoresizeoffthen resize the last column so that it pass the scrollpane width...then scroll the scrollpane to the right...there's a problem with the header painting...
shy_guya at 2007-7-14 22:27:37 > top of Java-index,Desktop,Core GUI APIs...
# 5
also seems to be a similar problem with another example of this http://www.objects.com.au/java/examples/swing/MultiWidthTableHeader.doperhaps it's just not designed to be resize_off
Michael_Dunna at 2007-7-14 22:27:37 > top of Java-index,Desktop,Core GUI APIs...
# 6
maybe, but i don't think so...i've tested the original code by mr nobuo, and resize_off it http://www.java2s.com/Code/Java/Swing-Components/GroupableGroupHeaderExample.htmit doesn't have painting problem, but aligment problem instead...and it's not multiline...
shy_guya at 2007-7-14 22:27:37 > top of Java-index,Desktop,Core GUI APIs...