简体   繁体   English

居中 JTable 列 header 时的外观问题

[英]Look-and-feel issue when centering JTable column header

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:在 JTable 列上:

    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:并且外观不再与其他列标题匹配:

在此处输入图像描述

Why?为什么? How can I solve this issue?我该如何解决这个问题?

EDIT编辑

It seems like NetBeans is using DefaultTableCellHeaderRenderer which is coming from package sun.swing.table;似乎 NetBeans 正在使用来自package sun.swing.table;DefaultTableCellHeaderRenderer

I read everywhere that I should not use sun packages.我到处都读到我不应该使用太阳包。 Grrrr... this does not help! Grrrr ......这没有帮助!

EDIT 2编辑 2

The suggestion of 0verbose produces the following: 0verbose 的建议产生以下结果:

在此处输入图像描述

SOLUTION解决方案

Following eugener's suggestion, I updated my code as following:根据 eugener 的建议,我将代码更新如下:

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:我明白了:

在此处输入图像描述

Look-and-feel is preserved and column header is centered,!!外观保留,header 列居中,!! (Other column headers are centered too, but I can control this by making further tests on the int row, int column parameters). (其他列标题也居中,但我可以通过对int row, int column参数进行进一步测试来控制这一点)。

The issue is that you are using different cell renderer then the one used by your LAF.问题是您使用的单元格渲染器与 LAF 使用的单元格渲染器不同。 IMO the only way to achieve proper LAF is to use renderer already provided by LAF itself such as: 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) {}

}

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.显然,一旦你有合适的渲染器,你可以将它转换为 JLabel(当然,在检查它之后),然后将你的文本居中或做其他事情。

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. DefaultTableCellRenderer已经扩展了 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) (我不确定。我做了类似的事情,但不是针对列 header 并且没有扩展 DefaultTableCellRenderer)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM