miércoles, 4 abril 2007

Displaying a jTable inside another jTable // JTable cellRenderer

Java is one of the greatest object oriented languages. This can easily be seen when using swing components. JTables are a great example. Briefly, jTables are just a base to display a matrix of JComponents. So inside a JTable you can embed any object which extends the JComponent class.
Today I'll show you an easy way to display a JTable inside another jTable as a cellRenderer. If you've ever worked with multivalued data models this can be of great help. In this simple example I'll create a small contact manager where the name, phones, and e-mail addresses of the contact can be stored. If the contact has more than one e-mail address or phone number, then they'll be displayed using an embedded jTable.

/* We initialize the Objects where we'll store our data */
/* First an array Object which will be our main table */
Object[][] data = null;
/* We create an Array String to hold the name of the main table columns In this example case we are going to store a contact name, his email address(es) and his phone numer(s) We're also going to store the creation date.*/
String[] columns = {"Name", "E-Mail","Phone","Creation Date"};
/* First thing is to populate our data object with some example values*/
public void populateData(){
/* Two contacts*/
data = new Object[3][columns.length];
data[0][0] = "Peter";
String[] emails = {"peter@yahoo.com", "strange@name.com"};
data[0][1] = emails;
String[] phones = {"555 35 25 65" , "555 35 24 63"};
data[0][2] = phones;
data[0][3] = new Date();
data[1][0] = "Jackson";
data[1][1] = "Jack@hotmail.com";
String[] phones2 = {"555 35 24 33" , "555 11 88 88", "332 55 25 34"};
data[1][2] = phones2;
data[1][3] = new Date();
data[2][0] = "Robert";
data[2][1] = "rob@hotmail.com";
data[2][2] = "555 28 95 81";
data[2][3] = new Date();
/* AS you can see, we've stored two contacts one with two e-mail
accounts and two phone numbers, and another member with three phone
numbers*/
}
/* Next we create our table models */
public void createModel(){
/* First we create the main model
We overide the AbstractTableModel necessary methods*/
AbstractTableModel modelo = new AbstractTableModel() {
public String getColumnName(int col) {
return columns[col].toString();
}
public Class getColumnClass(int col) {
if(getRowCount() <1)return null;
return data[0][col].getClass();
}
public int getRowCount() { return data.length; }
public int getColumnCount() { return columns.length;}
public Object getValueAt(int row, int col) {
return data[row][col];
}
public boolean isCellEditable(int row, int col){ return true; }
public void setValueAt(Object value, int row, int col) {
data[row][col] = value;
fireTableCellUpdated(row, col);
}};
/* We apply the model to the main jTable */
jTableData.setModel(modelo);
/* We create a cell Renderer to display the data of the multivalue
fields*/
TableCellRenderer jTableCellRenderer = new TableCellRenderer() {
/* These are necessary variables to store the row's height */
private int minHeight = -1;
private int currHeight = -1;
/* Magic Happens */
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
/* If what we're displaying isn't an array of values we
return the normal renderer*/
if(!value.getClass().isArray()){
return table.getDefaultRenderer(
value.getClass()).getTableCellRendererComponent(
table, value, isSelected, hasFocus,row, column);
}
else{
final Object[] passed = (Object[])value;
/* We calculate the row's height to display data
* THis is not complete and has some bugs that
* will be analyzed in further articles */
if(minHeight == -1){
minHeight = table.getRowHeight();
}
if(currHeight != passed.length*minHeight){
currHeight = passed.length * minHeight;
table.setRowHeight(row,currHeight);
}
/* We create the table that will hold the multivalue
*fields and that will be embedded in the main table */
return new JTable(
new AbstractTableModel() {
public int getColumnCount() {
return 1;
}
public int getRowCount() {
return passed.length;
}
public Object getValueAt(int rowIndex, int columnIndex) {
return passed[rowIndex];
}
public boolean isCellEditable(int row, int col){ return true; }
});
}
}
};
/* Finally we apply the new cellRenderer to the whole table */
TableColumnModel tcm = jTableData.getColumnModel();
for(int it = 0; it < tcm.getColumnCount(); it++){
tcm.getColumn(it).setCellRenderer(jTableCellRenderer);
}
/*Note: if we need to edit the values inside the embedded jtable
* we will need to create a TableCellEditor too. */

}

JTable with another embedded JTable

In the above image you can see the result. The code will only allow you to display the data, but you won't be able to edit. If you want to edit the data you must also create a table cell editor. I'll analyze this in further posts.

Technorati Tags:

Posted by admin at 1:20 PM in Java

Google
 
« April »
SunMonTueWedThuFriSat
1234567
891011121314
15161718192021
22232425262728
2930