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]

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