MyJTable

MyJTable a subclass of JTable only ment for displaying data.
You can't use MyJTable for input.
All data must be ready before creating MyJTable.

DISCLAIMER
Usual shit the use is at your own risk ;-)
Tested on: WindowsXP SP3, JDK version 1.6.0_10

Created by Comweb Netherlands
Freeware (GNU license)

Download MyJTable example


Screenshot:

MyJTableDemo.java
//
// This prints a table only for output.
// Data must be present before the creation of the table.
// Data must be in an array of Object[row][column]
// The first row are the headers of the table
//
// These Objects are of class CellContent.
// CellContent contains information about the look of the cell
// like Colors Font and Borders, alligment etceteras
// It also contains the value of the cell.
// It contstructor is:
// CellContent(Color bgcolor,Color color,Font font,int alignment,LineBorder lineBorder,String value )
//

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

public class MyJTableDemo
{
    public static void main(String[] args)
    {
            Object[][] data =
            {
                    // first row of cells are my header.
                    {
                            new CellContent(Color.LIGHT_GRAY,Color.BLACK,new Font(Font.MONOSPACED,Font.BOLD,15),JLabel.CENTER,new LineBorder(Color.BLACK,2,true),"AccountNumber"),
                            new CellContent(Color.LIGHT_GRAY,Color.BLACK,new Font(Font.MONOSPACED,Font.BOLD,15),JLabel.CENTER,new LineBorder(Color.BLACK,2,true),"AccountName"),
                            new CellContent(Color.LIGHT_GRAY,Color.BLACK,new Font(Font.MONOSPACED,Font.BOLD,15),JLabel.CENTER,new LineBorder(Color.BLACK,2,true),"DebetValue"),
                            new CellContent(Color.LIGHT_GRAY,Color.BLACK,new Font(Font.MONOSPACED,Font.BOLD,15),JLabel.CENTER,new LineBorder(Color.BLACK,2,true),"CreditValue")
                    },
                    // data cells
                    {new CellContent("010.00")        ,new CellContent("Eigen Vermogen")        ,new CellContent("")                ,new CellContent("10000")        },
                    {new CellContent("100.00")        ,new CellContent("Bank")                        ,new CellContent("5000")        ,new CellContent("")                },
                    {new CellContent("120.00")        ,new CellContent("Debiteuren")                ,new CellContent("4800")        ,new CellContent("")                },
                    {new CellContent("")                ,new CellContent("Verlies")                        ,new CellContent("200")                ,new CellContent("")                },
                };

            // create a frame for displaying
            JFrame frame=new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                MyJTable myJTable = new MyJTable(data);
                // change one cell as demo
                CellContent contentTest=new CellContent(Color.GREEN,Color.RED,new Font(Font.MONOSPACED,Font.BOLD,18),JLabel.RIGHT,new LineBorder(Color.BLUE,5,true),"TEST");
                myJTable.getModel().setValueAt((Object)contentTest,2,0);
                myJTable.packRows(1); // finally resize the rows so the components fit.

                JScrollPane jscrollPane=new JScrollPane(myJTable);
                frame.getContentPane().add(jscrollPane,BorderLayout.CENTER);
                frame.pack();
                frame.setExtendedState(frame.getExtendedState()|JFrame.MAXIMIZED_BOTH);
                frame.setVisible(true);
    }
}

MyJTable.java
//
// MyJTable is a subclass of JTable.
//
// It works together with MyRenderer,MyTableModel and CellContent.
//

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

public class MyJTable extends JTable
{

    public MyJTable(Object[][] rowData)
    {
            super(rowData,getMyHeaders(rowData)); // Call super to precreate a JTabel
            MyTableModel myTableModel = new MyTableModel(rowData);
        this.setModel(myTableModel); // use MyTableModel (contains the Table data)
        this.setDefaultRenderer(CellContent.class, new MyRenderer());  // use MyRenderer as default Renderer
        this.getTableHeader().setReorderingAllowed(false); // no reordering
                this.getTableHeader().setResizingAllowed(false); // no resizing
                this.setTableHeader(null);        // no headers
    }

    public static Object[] getMyHeaders(Object[][] rowData)
    {
            // this method returns an Object[] with empty Strings
            // This is to satisfy JTable(Object rowData[][],Object[] columnNames) constructor
            //
            // I THINK internally JTable uses Strings for displaying the headers.
            // It was not possible to use MyRenderer for the headers.
            // Because the headers names are sent as Strings to MyRenderer.
            // That should be CellContent.
            //
            // Because of that we omited the Headers
            // (this.setTableHeader(null);)
            //
            Object[] columnNames=new Object[rowData[0].length];
                for(int column=0;column<rowData[0].length;column++)
                {
                        columnNames[column]="";
                }
                return columnNames;
    }

    public int getPreferredRowHeight(int rowIndex, int margin)
    {
        // Get the current default height for all rows
        int height = this.getRowHeight();

        // Determine highest cell in the row
        for (int c=0; c<this.getColumnCount(); c++)
        {
            TableCellRenderer renderer = this.getCellRenderer(rowIndex, c);
            Component comp = this.prepareRenderer(renderer, rowIndex, c);
            int h = comp.getPreferredSize().height + 2*margin;
            height = Math.max(height, h);
        }
        return height;
    }

    public void packRows(int margin)
    {
        for (int r=0; r<this.getRowCount(); r++)
        {
            // Get the preferred height
            int h = getPreferredRowHeight( r, margin);

            // Now set the row height using the preferred height
            if (this.getRowHeight(r) != h)
            {
                this.setRowHeight(r, h);
            }
        }
    }

	 @Override // Tells compiler to extra check that it overrides a method (optional)
    public void tableChanged(TableModelEvent e)
    {
            // think this method can be omited :-)
            // just for debugging I added it.
                super.tableChanged(e);
            return;
    }
}

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

public class MyTableModel extends AbstractTableModel
{

     public Object[] columnNames=new Object[0];
     public Object[][] rowData=new Object[0][0];

     public MyTableModel(Object[][] rowData)
     {
         this.columnNames=MyJTable.getMyHeaders(rowData); // get it correct
         for(int column=0;column<rowData[0].length;column++)
			{
         	this.columnNames[column]="";
         }
         this.rowData=rowData;
		}

	  	@Override // Tells compiler to extra check that it overrides a method (optional)
      public String getColumnName(int col)
      {
        	return columnNames[col].toString();
    	}

      @Override // Tells compiler to extra check that it overrides a method (optional)
      // inherited from interface javax.swing.table.TableModel
      // (AbstractTableModel implements interface javax.swing.table.TableModel)
		public int getRowCount()
    	{
        	return rowData.length;
    	}

      @Override // Tells compiler to extra check that it overrides a method (optional)
      // inherited from interface javax.swing.table.TableModel
      // (AbstractTableModel implements interface javax.swing.table.TableModel)
      public int getColumnCount()
      {
         return columnNames.length;
      }

      @Override // Tells compiler to extra check that it overrides a method (optional)
      // inherited from interface javax.swing.table.TableModel
      // (AbstractTableModel implements interface javax.swing.table.TableModel)
      public Object getValueAt(int row, int col)
      {
         return rowData[row][col];
      }

      @Override // Tells compiler to extra check that it overrides a method (optional)
      public boolean isCellEditable(int row, int col)
      {
          return false; // non of the my cells are editable, we only display data.
      }

      @Override // Tells compiler to extra check that it overrides a method (optional)
      public void setValueAt(Object value, int row, int col)
      {
        // remember value must be CellContent.
        rowData[row][col] = value;
        fireTableCellUpdated(row, col);
    }

    @Override // Tells compiler to extra check that it overrides a method (optional)
    public Class getColumnClass(int c)
    {
            /*
                    From SUN example
                    Remember that if you let a table create its own model,
                    it uses Object as the type of every column.
                    To specify more precise column types, the table model
                    must define the getColumnClass method appropriately, as demonstrated by
            */
            // I not uderstand this :-))
            //
        return getValueAt(0, c).getClass();
    }
}

MyRenderer.java
//
// MyRenderer determines how the Cell should be drawn
// Depending on the information found inside CellContent
//

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

public class MyRenderer extends JLabel implements TableCellRenderer
{
        public MyRenderer()
    {
            super();
            setOpaque(true); // background must show
    }

    public Component getTableCellRendererComponent(
                                                   JTable table,
                                                   Object cellContent,
                                                   boolean isSelected,
                                                   boolean hasFocus,
                                                   int row,
                                                   int column)
    {
            if (cellContent==null) return this; // should not be :-)
            CellContent content=(CellContent)cellContent; // We only cast one time to speed up.
            // use information about the cell look
            this.setBackground(content.getBackground());
            this.setForeground(content.getForeground());
            this.setFont(content.getFont());
            this.setHorizontalAlignment(content.getHorizontalAlignment());
            if (content.getLineBorder()!=null)
            {
                    this.setBorder(content.getLineBorder());
            } else
            {
                    this.setBorder(null);
            }
            // set the value of the cell
            this.setText(content.getValue());
            return this;
    }
}

CellContent.java
//
// CellContent conatins all information about a particular cell
// It is used by MyRenderer to display it.
// It contains background color, font color,
// font, Horizontal alignment, border
// and also the value of the cell (allways String).
//

import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;

public class CellContent
{
        private Color bgcolor=Color.WHITE; // background color
        private Color color  =Color.BLACK; // foreground color
        private Font  font         =new Font(Font.MONOSPACED,Font.PLAIN,12);
        private int alignment=JLabel.LEFT; // default alignment is left
        private LineBorder lineBorder=null;
        private String value ="";

        public CellContent() {}
        public CellContent(String value)
        {
                this(null,null,null,JLabel.LEFT,null,value);
        }
        public CellContent(Color bgcolor,Color color,Font font,int alignment,LineBorder lineBorder,String value )
        {
                if (bgcolor!=null) { this.bgcolor=bgcolor; }
                if (color!=null)   { this.color=color; }
                if (font!=null)    { this.font=font;}
                this.alignment=alignment;
                if (lineBorder!=null) {this.lineBorder=lineBorder;}
                if (value!=null)   { this.value=value;}
        }

        public Color getBackground()                        { return bgcolor; }
        public Color getForeground()                        { return color; }
        public Font getFont()                               { return font; }
        public int getHorizontalAlignment()                 { return alignment; }
        public LineBorder getLineBorder()                   { return lineBorder; }
        public String getValue()                            { return value; }
        public void setBackground(Color bgcolor)            { this.bgcolor=bgcolor; }
        public void setForeground(Color color)              { this.color=color; }
        public void setFont(Font font)                      { this.font=font; }
        public void setHorizontalAlignment(int alignment)   { this.alignment=alignment; }
        public void setLineBorder(LineBorder lineBorder)    { this.lineBorder=lineBorder;}
        public void setValue(String value)                  { this.value=value; }
}