2

I am using the following code:

public final class TableCellRendererCenter extends DefaultTableCellRenderer {

    public static final TableCellRenderer INSTANCE
            = new TableCellRendererCenter();

    protected TableCellRendererCenter() {

        // Calling super
        super();

        this.setHorizontalAlignment(SwingConstants.CENTER);

    }

}

on a JTable column:

    TableColumnModel retrMod = ChartItemsTable.getColumnModel();
    TableColumn retrCol = retrMod.getColumn(2);

    retrCol.setHeaderRenderer(TableCellRendererCenter.INSTANCE);
    retrCol.setCellRenderer(TableCellRendererCenter.INSTANCE);

and the look-and-feel does not match other column headers anymore:

enter image description here

Why? How can I solve this issue?

EDIT

It seems like NetBeans is using DefaultTableCellHeaderRenderer which is coming from package sun.swing.table;

I read everywhere that I should not use sun packages. Grrrr... this does not help!

EDIT 2

The suggestion of 0verbose produces the following:

enter image description here

SOLUTION

Following eugener's suggestion, I updated my code as following:

public final class TableCellRendererCenter extends DefaultTableCellRenderer {

    @Override
    public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column) {

        // returns component used for default header rendering
        // makes it independent on current L&F

        Component retr = table.getTableHeader().getDefaultRenderer().
            getTableCellRendererComponent(
                table, value, isSelected, hasFocus, row, column);

        if ( JLabel.class.isAssignableFrom(retr.getClass()) ) {

            JLabel jl = (JLabel) retr;
            jl.setHorizontalAlignment(SwingConstants.CENTER);

        }

        return retr;

    }

    @Override
    public void validate() {}

    @Override
    public void revalidate() {}

    @Override
    public void firePropertyChange(
        String propertyName, boolean oldValue, boolean newValue) {}

    @Override
    public void firePropertyChange(
        String propertyName, Object oldValue, Object newValue) {}

}

And I get this:

enter image description here

Look-and-feel is preserved and column header is centered !!! (Other column headers are centered too, but I can control this by making further tests on the int row, int column parameters).

Jérôme Verstrynge
  • 57,710
  • 92
  • 283
  • 453

2 Answers2

5

The issue is that you are using different cell renderer then the one used by your LAF. IMO the only way to achieve proper LAF is to use renderer already provided by LAF itself such as:

public class TableHeaderRenderer extends JComponent implements TableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
                        boolean hasFocus, int row, int column) {

                // returns component used for default header rendering
                // makes it independent on current L&F

        return table.getTableHeader().getDefaultRenderer().
                          getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

        }

        // following methods are overriden for performance reasons

        @Override
        public void validate() {}

        @Override
        public void revalidate() {}

        @Override
        public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {}

        @Override
        public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {}

}

Obviously, once you have proper renderer, you can cast it to a JLabel (after checking that it is, of course) and then center your text or do something else.

Eugene Ryzhikov
  • 17,131
  • 3
  • 38
  • 60
2

maybe you can try refactor yourclass this way :

public class TableCellRendererCenter extends JLabel implements TableCellRenderer{

public TableCellRendererCenter(JTable associatedTable){

    this.table = associatedTable;
    JTableHeader header = this.table.getTableHeader();

    this.setHorizontalAlignment(SwingConstants.CENTER);
    this.setForeground(header.getForeground());
    this.setBackground(header.getBackground());
    this.setFont(header.getFont());

}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

    return this;

}}

EDIT: I checked right now. DefaultTableCellRenderer already extends JComponent. So it's possible that only these lines are needed:

this.setForeground(header.getForeground());
this.setBackground(header.getBackground());
this.setFont(header.getFont());

(I'm not sure. I did something similar but not for column header and not extending DefaultTableCellRenderer)

Heisenbug
  • 38,762
  • 28
  • 132
  • 190