Search code examples
javaswingjtablejlabelimageicon

How to put text next to my ImageIcon on a cell in a JTable


I have an application that works with a JTable, and in this JTable, I want each cell to have both an ImageIcon and some text.

I see at this link (https://docs.oracle.com/javase/tutorial/uiswing/components/table.html#editrender), JTable supports ImageIcon OR text, but seemingly not both at the same time.

I also see that on the bullet for ImageIcon, it says rendered by a centered label.

Well, I know for a fact that I can put both an ImageIcon and text together on the same JLabel -- I am doing that already for a different part of my application.

How do I get access to that JLabel, so that I can put some text alongside that icon?


Solution

  • I have been informed that my question is actually a duplicate. Here is a link to the original question.

    https://stackoverflow.com/a/52065145/131872

    But I can provide a bit more detail to how I implemented it for me.

    In my case, I want to store both an ImageIcon and some text. So, the first thing I should do is create a data type that contains both of these elements.

    record TextIcon(String text, ImageIcon icon) {}
    

    Next, I need to create a renderer that can render this data type. To do that, I will extend the DefaultTableCellRenderer.

       
          final class MyTableCellRenderer extends DefaultTableCellRenderer
          {
          
             @Override
             public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
             {
             
                super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
             
                if (value instanceof TextIcon textIcon)
                {
                
                   this.setText(textIcon.text());
                   this.setIcon(textIcon.icon());
                
                }
             
                return this;
             
             }
          }
       
    

    Doing it this way is nice because, now, I don't need to specify which column this applies to. I can apply this renderer to all of my columns, and then if they are not a TextIcon, they will just do the default rendering they would have gotten.

    Alternatively, if I need to create another data type for my table, I can just add another if statement to this method. This strategy is a powerful way to add custom rendering to your table.

    Now that I have my renderer, I will add it to all of my columns. Here is the easiest way to do it.

    table.setDefaultRenderer(Object.class, new MyTableCellRenderer());
    

    I use Object.class because I want this renderer to be used for all columns. Since Object is a parent to all reference data types, then doing this essentially means that I am applying this renderer to all of my columns.

    After that, I just continue as is, and things just work!