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 7.2 is now available!
  • Connecting to an MCP Server from JavaScript using AI SDK
  • Connecting to an MCP Server from JavaScript using LangChain.js
  • The Future of Developer Tools: Adapting to Machine-Based Developers
  • Connecting to a Model Context Protocol (MCP) Server from Java using LangChain4j

Categories

  • Artificial Intelligence
  • Front-end
  • Go
  • Industry and business
  • Java
  • JavaScript
  • Legacy
  • Operations
  • Personal
  • Pet projects
  • Tools

Archives

  • May 2025
  • April 2025
  • March 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • August 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • March 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • May 2022
  • March 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
  • February 2020
  • January 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
  • January 2017
  • December 2015
  • November 2015
  • December 2014
  • March 2014
  • February 2011
  • November 2008
  • June 2008
  • May 2008
  • April 2008
  • January 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: 2023-10-31

Note

This code in this post has been updated, you can find it here.

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.

In this post, 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.

Let's start by defining some variables to hold the data for our example's model:

// We declare the variables where we'll store our data
// First an array Object which will be our main table
Object[][] data = null;
// We declare an Array String to hold the name of the main table columns
// In this example case we are going to store:
//   contact name, email address(es), phone number(s) and  creation date.
String[] columns = {"Name", "E-Mail","Phone","Creation Date"};

Next, let's create a function to populate the variables with some sample data:

// First, 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 */
}

Finally, we create our table models and the cell renderer that will allow us to display the data in a nested JTable:

// 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];
    }
    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.
}

If everything goes well, you should see a table like the following:

Screenshot of the resulting nested JTable
Screenshot of the resulting nested JTable

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 - 2025 Marc Nuri