Неприятная проблема при центрировании заголовка столбца JTable - PullRequest
2 голосов
/ 30 июня 2011

Я использую следующий код:

public final class TableCellRendererCenter extends DefaultTableCellRenderer {

    public static final TableCellRenderer INSTANCE
            = new TableCellRendererCenter();

    protected TableCellRendererCenter() {

        // Calling super
        super();

        this.setHorizontalAlignment(SwingConstants.CENTER);

    }

}

в столбце JTable:

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

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

, и внешний вид больше не соответствует другим заголовкам столбцов:

enter image description here

Почему?Как я могу решить эту проблему?

РЕДАКТИРОВАТЬ

Похоже, что NetBeans использует DefaultTableCellHeaderRenderer, который идет от package sun.swing.table;

Я прочиталвезде, где я не должен использовать солнцезащитные пакеты.Grrrr ... это не помогает!

РЕДАКТИРОВАТЬ 2

Предложение 0verbose дает следующее:

enter image description here

РЕШЕНИЕ

Следуя совету Евгения, я обновил свой код следующим образом:

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) {}

}

И я получил это:

enter image description here

Внешний вид сохранен, а заголовок столбца центрирован !!!(Другие заголовки столбцов тоже центрированы, но я могу контролировать это, проводя дальнейшие проверки параметров int row, int column).

Ответы [ 2 ]

5 голосов
/ 30 июня 2011

Проблема в том, что вы используете другой рендерер ячеек, чем тот, который использовался вашим LAF.IMO единственный способ добиться правильного LAF - это использовать рендерер, уже предоставленный самим LAF , например:

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) {}

}

Очевидно, что после того, как у вас есть подходящий рендерер, вы можете привести его к JLabel(после проверки, конечно, это так), а затем отцентрируйте текст или сделайте что-нибудь еще.

2 голосов
/ 30 июня 2011

может быть, вы можете попробовать рефакторинг вашего класса следующим образом:

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;

}}

РЕДАКТИРОВАТЬ: Я проверил прямо сейчас. DefaultTableCellRenderer уже расширяет JComponent.Поэтому возможно, что нужны только эти строки:

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

(я не уверен. Я сделал нечто подобное, но не для заголовка столбца и не расширял DefaultTableCellRenderer)

...