Search code examples
javaswingjtableiconslook-and-feel

Inserting images into JTable cell with GTKLookAndFeel


The issue appears to be the system look and feel for Linux/Ubuntu because it works in Windows and other look and feels. I can't seem to find any way to fix this. I am currently using Ubuntu 15.10.

// Set my look and feel in main()
// Printed out: "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"
try {
    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Throwable e) {}


// I set my table to render images inside the ui method. Works with every other look and feel.
ImageIcon document = new ImageIcon(Toolkit.getDefaultToolkit().getImage(this.getClass().getResource("/test/documents.png")));
DefaultTableModel model = new DefaultTableModel(new Object[]{"A","B"},0);
table = new JTable(model);
table.setRowHeight(document.getIconHeight());
table.getColumnModel().getColumn(0).setCellRenderer(table.getDefaultRenderer(ImageIcon.class));
for(int i=0; i<10; i++)
    model.addRow(new Object[]{document,i});

// When the L&F is set to GTK, the table will just print out Object.toString()
// For example: "javax.swing.ImageIcon@e957ef0"

I realize I can switch my look and feel but is there a reason this doesn't work with GTK and is there a way to get around it?

When printing out table.getDefaultRenderer(Icon.class) for the table it is not null but returns the following:

javax.swing.plaf.synth.SynthTableUI$SynthTableCellRenderer[Table.cellRenderer,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.0,border=javax.swing.plaf.synth.SynthBorder@3d04a311,flags=8388608,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,horizontalAlignment=LEADING,horizontalTextPosition=TRAILING,iconTextGap=4,labelFor=,text=,verticalAlignment=CENTER,verticalTextPosition=CENTER]

Using a custom default renderer works. I took the IconRenderer class from the JTable source which fixed new issues when making the custom renderer such as centering the image and no indication you selected the cell.

import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.table.DefaultTableCellRenderer;

class IconRenderer extends DefaultTableCellRenderer.UIResource {
    public IconRenderer() {
        super();
        setHorizontalAlignment(JLabel.CENTER);
    }

    public void setValue(Object value) {
        setIcon((value instanceof Icon) ? (Icon) value : null);
    }
}

Solution

  • Well you can always add a:

     System.out.println( table.getDefaultRenderer(Icon.class) );
    

    statement to see what is returned. I always use Icon so any kind of Icon can be displayed.

    is there a way to get around it?

    If it is null then you know GTK doesn't have a default renderer so you would need to create your own Icon renderer. Check out the section from the Swing tutorial on Using Custom Renderers for more information.