Search code examples
javajtablerenderer

Align text in a JTable cell while maintaining JTable default renderer?


I have a JTable that does lovely alternations in coloration thanks to this code:

table.setDefaultRenderer(Object.class, new BorderRenderer(new ColorRenderer(table
                .getDefaultRenderer(Object.class), colorProvider)));

(Here the "colorProvider" contains code that turns every other row light grey.) I have one column in which I would like to align text to center. If I simply set a DefaultCellRenderer on that column with center horizontal alignment, it overrides the table's default renderer and I lose my lovely stripes.

Can I keep the stripes and still change the alignment of a column?

To further complicate things, I have the above code in a super class. It is my sub classes that know what column(s) they would like to change the alignment on.


Solution

  • Thanks both to afk and camickr who led me to my final decision to write a TableCellRendererWrapper:

    public class ColumnAlignmentRenderer implements TableCellRenderer {
    
        private TableCellRenderer mWrappedRenderer;
        private int mDefaultAlignment = SwingConstants.LEFT;
        private Map<Integer, Integer> mSpecialColumnAlignmentMap = new Hashtable<Integer, Integer>();
    
        public ColumnAlignmentRenderer(TableCellRenderer pWrappedRenderer) {
            mWrappedRenderer = pWrappedRenderer;
        }
    
        public Component getTableCellRendererComponent(JTable pTable, Object pValue, boolean pIsSelected,
                boolean pHasFocus, int pRow, int pColumn) {
    
            // Use the wrapped renderer
            Component renderedComponent = mWrappedRenderer.getTableCellRendererComponent(pTable, pValue, pIsSelected, pHasFocus,
                    pRow, pColumn);
    
            // Set the alignment
            Integer alignment = mSpecialColumnAlignmentMap.get(pColumn);
            if (alignment != null) {
                ((JLabel)renderedComponent).setHorizontalAlignment(alignment);
            } else {
                ((JLabel)renderedComponent).setHorizontalAlignment(mDefaultAlignment);
            }
    
            return renderedComponent;
        }
    
        public void setSpecialColumnAlignment(Integer pColumn, Integer pAlignment) {
            mSpecialColumnAlignmentMap.put(pColumn, pAlignment);
        }
    
        public void setDefaultAlignment(int pAlignment) {
            mDefaultAlignment = pAlignment;
        }
    }
    

    It's not perfect, but it gets the job done for me. To use it I do this:

            // Center alignment for "selected" column
            ColumnAlignmentRenderer cellRenderer = new ColumnAlignmentRenderer(getTable().getDefaultRenderer(Object.class));
            cellRenderer.setSpecialColumnAlignment(MyTableModel.COL_TO_CENTER, SwingConstants.CENTER);
            getTable().setDefaultRenderer(Object.class, cellRenderer);
    
            // Center alignmet for "selected" column header
            ColumnAlignmentRenderer headerRenderer = new ColumnAlignmentRenderer(getTable().getTableHeader().getDefaultRenderer());
            headerRenderer.setSpecialColumnAlignment(MyTableModel.COL_TO_CENTER, SwingConstants.CENTER);
            getTable().getTableHeader().setDefaultRenderer(headerRenderer);