A logo showing the text blog.marcnuri.com
Español
Home»Java»Displaying a jTable inside another jTable // JTable cellRenderer

Recent Posts

  • Fabric8 Kubernetes Client 6.5.0 is now available!
  • Eclipse JKube 1.11 is now available!
  • Fabric8 Kubernetes Client 6.4.1 is now available!
  • I bought an iPad
  • Three years at Red Hat

Categories

  • Front-end
  • Java
  • JavaScript
  • Legacy
  • Operations
  • Personal
  • Pet projects
  • Tools

Archives

  • March 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • May 2022
  • February 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • August 2021
  • July 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • December 2019
  • October 2019
  • September 2019
  • July 2019
  • March 2019
  • November 2018
  • July 2018
  • June 2018
  • May 2018
  • April 2018
  • March 2018
  • February 2018
  • December 2017
  • July 2017
  • December 2015
  • November 2015
  • November 2008
  • November 2007
  • September 2007
  • August 2007
  • July 2007
  • June 2007
  • May 2007
  • April 2007
  • March 2007

Displaying a jTable inside another jTable // JTable cellRenderer

2007-04-04 in Java / Legacy tagged Embedded / Java / JTable / Multivalue / Swing by Marc Nuri | Last updated: 2021-02-06

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.

1// We declare the variables where we'll store our data
2// First an array Object which will be our main table
3Object[][] data = null;
4// We declare an Array String to hold the name of the main table columns
5// In this example case we are going to store:
6//   contact name, email address(es), phone number(s) and  creation date.
7String[] columns = {"Name", "E-Mail","Phone","Creation Date"};
1// First, populate our data object with some example values
2public void populateData(){
3  /* Two contacts*/
4  data = new Object[3][columns.length];
5  data[0][0] = "Peter";
6  String[] emails = {"peter@yahoo.com", "strange@name.com"};
7  data[0][1] = emails;
8  String[] phones = {"555 35 25 65" , "555 35 24 63"};
9  data[0][2] = phones;
10  data[0][3] = new Date();
11  data[1][0] = "Jackson";
12  data[1][1] = "Jack@hotmail.com";
13  String[] phones2 = {"555 35 24 33" , "555 11 88 88", "332 55 25 34"};
14  data[1][2] = phones2;
15  data[1][3] = new Date();
16  data[2][0] = "Robert";
17  data[2][1] = "rob@hotmail.com";
18  data[2][2] = "555 28 95 81";
19  data[2][3] = new Date();
20  /* As you can see, we've stored two contacts one with two e-mail accounts and two phone numbers,
21  and another member with three phone numbers */
22}
23// Next, we create our table models
24public void createModel(){
25  /* First we create the main model
26  We overide the AbstractTableModel necessary methods*/
27  AbstractTableModel modelo = new AbstractTableModel() {
28    public String getColumnName(int col) {
29      return columns[col];
30    }
31    public Class getColumnClass(int col) {
32      if(getRowCount() <1) {
33        return null;
34      }
35      return data[0][col].getClass();
36    }
37    public int getRowCount() {
38      return data.length;
39    }
40    public int getColumnCount() {
41      return columns.length;
42    }
43    public Object getValueAt(int row, int col) {
44      return data[row][col];
45    }
46    public boolean isCellEditable(int row, int col){
47      return true;
48    }
49    public void setValueAt(Object value, int row, int col) {
50      data[row][col] = value; fireTableCellUpdated(row, col);
51    }
52  };
53  /* We apply the model to the main jTable */
54  jTableData.setModel(modelo);
55  /* We create a cell Renderer to display the data of the multivalue fields*/
56  TableCellRenderer jTableCellRenderer = new TableCellRenderer() {
57    /* These are necessary variables to store the row's height */
58    private int minHeight = -1;
59    private int currHeight = -1;
60    /* Magic Happens */
61    public Component getTableCellRendererComponent(
62        JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
63      /* If what we're displaying isn't an array of values we return the normal renderer*/
64      if(!value.getClass().isArray()){
65        return table.getDefaultRenderer(value.getClass())
66            .getTableCellRendererComponent(table, value, isSelected, hasFocus,row, column);
67      } else{
68        final Object[] passed = (Object[])value;
69        /* We calculate the row's height to display data 
70        *  This is not complete and has some bugs that
71        *  will be analyzed in further articles */
72        if(minHeight == -1){
73          minHeight = table.getRowHeight();
74        }
75        if(currHeight != passed.length*minHeight){
76          currHeight = passed.length * minHeight;
77          table.setRowHeight(row,currHeight);
78        }
79        /* We create the table that will hold the multivalue
80        *  fields and that will be embedded in the main table */
81        return new JTable(new AbstractTableModel() {
82          public int getColumnCount() {
83            return 1;
84          }
85          public int getRowCount() {
86            return passed.length;
87          }
88          public Object getValueAt(int rowIndex, int columnIndex) {
89            return passed[rowIndex];
90          }
91          public boolean isCellEditable(int row, int col){
92            return true;
93          }
94        });
95      }
96    }
97  }; /* Finally we apply the new cellRenderer to the whole table */
98  TableColumnModel tcm = jTableData.getColumnModel();
99  for(int it = 0; it < tcm.getColumnCount(); it++){
100    tcm.getColumn(it).setCellRenderer(jTableCellRenderer);
101  }
102  // Note: if we need to edit the values inside the embedded jtable
103  // we will need to create a TableCellEditor too.
104}
Screenshot of the resulting embedded JTable
Screenshot of the resulting 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.

Twitter iconFacebook iconLinkedIn iconPinterest iconEmail icon

Comments in "Displaying a jTable inside another jTable // JTable cellRenderer"

  • Avatar for Chris
    Chris
    2007-08-01 23:12
    Hello -- any chance you'll be updating this any time soon? I'm using the code, and it works, but I'd like to be able to find out which row was clicked on the inner (embedded) table.

    Also, I sent you email, and it bounced with a "Message could not be delivered to the domain - marcnuri.com." message.
  • Avatar for Marc Nuri
    Marc Nuri
    2007-08-02 08:32
    The problem with this is that what you click when clicking the embedded table is just the visible representation of your data. To be able to manage this data you'll have to create your own TableCellEditor just as we created the TableCellRenderer. When I get some spare time maybe I'll do a tutorial.

    For the time being you can try adapting this code Creating a Custom Table Cell Editor in a JTable Component

    About the E-Mail bouncing, maybe the server was down when you tried, thanks for the heads-up.
  • Avatar for Andrea
    Andrea
    2007-08-02 16:07
    Hello,

    thanks for your code, it was really useful to me but I have some problems when I display the table, if I go to other window then when I return, the table and also the menu and other components that I have in the same window where is the table disappear, you know why its happening this??

    Thanks a lot.
  • Avatar for Chris
    Chris
    2007-08-02 21:04
    Hi Marc -- thanks for the quick response and the link. I appreciate it!
  • Avatar for fado
    fado
    2008-03-04 02:34
    please help me in creating cell editing for embbed jtable also. need your please

    thanks
  • Avatar for Kohlerfc
    Kohlerfc
    2010-08-11 02:54
    Hi Thanks for the post, it helped me go in the right direction. Just a note could you please format your code as it is very difficult to read.
  • Avatar for Tarun
    Tarun
    2010-08-18 12:07
    Nice description.

    I have question.Can we add Combox in Jtable header e.g. if we select any action in combo box then it affects whole table (e.g. table bacground color) ?
  • Avatar for Sakret
    Sakret
    2011-09-01 08:01
    Hi, I have a problem, I copy this code and paste it in my java class (main class) but when I run it it only says "BUILD SUCCESSFUL (total time: 1 second)" maybe because of this

    public static void main(String[] args) {
    }

    what should I do? Thanks!
  • Avatar for Amit
    Amit
    2012-01-06 09:42
    Hi Marc,

    I am trying to use it to make nested tables n levels deep but unable to select the cell present in inner table. Could you please help by suggesting the way forward?
  • Avatar for Rubens Pereira
    Rubens Pereira
    2012-11-19 03:05
    Olá como faco pra mudar a cor de uma célula do jTable quando a coluna de status de um cliente for pago ou a receber

    Uso o jtable do Netbeans
  • Avatar for Karoline
    Karoline
    2013-01-06 19:32
    There was an issue on rhel4 where if a tracing preoscs didn't call ptrace detach that the thread group leader would stay in traced state. If someone sent it a SIGCONT the thread group leader would continue and all the child threads would go into a traced state (T in ps). A second SIGCONT would bring it back to normal. Between the two signals a ps ax would show only the thread group leader status. Be sure to check the threads in ps to make sure none of them are in a traced state.
  • Avatar for Prashanth
    Prashanth
    2020-06-30 13:56
    Hi Marc,

    Thank you, the code is perfectly working for me.

    If I try to copy the table data, the embedded cell values are copied as an Object
    i.e. Peter [Ljava.lang.Object;@20785a37 [Ljava.lang.Object;@2d649736 04-abr-2007

    How can i copy the data as it is for embedded cells instead of Objects.

Post navigation

← Java recursive functions explained // Using recursion to sum an array of numbersJava App for PostgreSQL scheduled backups using pg_dump (Windows only) →
© 2007 - 2023 Marc Nuri