【问题标题】:Set JTable header horizontal alignment based on value renderer column alignment根据值渲染器列对齐设置 JTable 标题水平对齐
【发布时间】:2016-01-26 02:58:57
【问题描述】:

我查看了许多关于设置 JTable 标头对齐的问题/答案,但它们似乎并未涵盖这种情况。我希望我的 JTable 标题与它们下面的数据具有相同的对齐方式;让它们都居中对我来说看起来很奇怪,特别是对于那些为偶尔的长字符串留出空间但通常只包含短字符串的列——标题本身就在空间的中心。

我见过的许多解决方案都依赖于 DefaultCellTableRenderer —— 是所有表头都使用吗?我不想设置 default 渲染器,因为这会改变 all 列;我想编写代码来计算列中数据的水平对齐方式,并将标题设置为在水平对齐方面做同样的事情。

我是否必须从渲染器中获取组件(使用特定的行、列和值)并在组件上设置对齐方式?我是否必须为此编写标题的自定义渲染器?最干净的整体方法是什么?

--编辑

先生。 Camick 的解决方案很优雅,几乎可以满足我的要求;它拦截为列标题创建表格单元格渲染器。不知何故,我所做的事情消除了标题的正常格式,但是 - 我的标题上没有阴影和边框(尽管它们按照我的意愿对齐!)。

我目前有以下内容:我在哪里可以得到表头的渲染器,所以我可以改变它的对齐方式?

import java.awt.Component;

import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

public class TableHeaderRenderer implements TableCellRenderer
{
    TableCellRenderer olderRenderer = null;

    public TableHeaderRenderer(TableCellRenderer givenRenderer)
    {
        olderRenderer = givenRenderer;
    }

//  // get the default renderer for the table header.
//  JTableHeader header = table.getTableHeader();
//  TableCellRenderer defaultRenderer = header.getDefaultRenderer();

    @Override
    public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column)
    {
        try // if the casts fail, we end up in the catch below
    {
        // get the renderer for the first row
        DefaultTableCellRenderer firstRowTableCellRenderer = (DefaultTableCellRenderer)table.getCellRenderer(0, column);

        // get the renderer for this column header
        JTableHeader tableHeader = table.getTableHeader();
        TableColumnModel columnModel = tableHeader.getColumnModel();
        TableColumn tableColumn = columnModel.getColumn(column);
        DefaultTableCellRenderer headerRenderer = (DefaultTableCellRenderer)tableColumn.getCellRenderer();

        // if the renderer for the column is null, create one
        if (headerRenderer == null) 
        { headerRenderer =  new DefaultTableCellRenderer(); 
        }

        // finally -- set the header's horizontal alignment to be the same as
        // that for the first row, then get the component 
        headerRenderer.setHorizontalAlignment(firstRowTableCellRenderer.getHorizontalAlignment());
        Component result = headerRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

        return result;
    }
        catch (ClassCastException cce)
        {
            // either the first row or the header has a renderer that isn't a DefaultTableCellRenderer
            // just return the component we already have
            return olderRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        }
    }

}

--

好的,编辑 2:

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;

@SuppressWarnings("serial")
public class TableHeaderRendererDemo extends JFrame
{
    Object[][]data = { {new Integer(1), "two", "three"},
                   { new Integer(4), "five", "six" }
                     };
    Object[] columnNames = { "first", "second", "third" };

    public static void main(String ... arguments) 
    { new TableHeaderRendererDemo().go(); 
    }

    public void go()
    {
        JTable table = new JTable(data, columnNames);
        JScrollPane scrollPane = new JScrollPane(table);

        // set our own default renderer for the headers
        JTableHeader header = table.getTableHeader();
        try 
        { DefaultTableCellRenderer defaultRenderer = (DefaultTableCellRenderer)header.getDefaultRenderer();
            header.setDefaultRenderer(new TableHeaderRenderer(defaultRenderer));
        }
        catch (ClassCastException e)
        {
            System.err.println("Could not cast default renderer; table headers not aligned");
        }

        add(scrollPane, BorderLayout.CENTER);
        pack();
        setVisible(true);
    }
}

你可以看到我所说的标题问题;我希望整数默认为右对齐,但由于某种原因他们没有。但是您可以从中看到我遇到的问题。

【问题讨论】:

  • 您真正遇到的问题不是所有TableCellRenders 都将基于DefaultCellRenderer 并且可能每个单元格都有自己的对齐方式,这取决于数据而有所不同
  • 我确实意识到了,其实...

标签: java swing jtable alignment jtableheader


【解决方案1】:

这是一个自定义标题渲染器的示例,它只是将所选列的文本变为粗体:

class MyTableHeaderRenderer implements TableCellRenderer
{
    private TableCellRenderer tableCellRenderer;

    public MyTableHeaderRenderer(TableCellRenderer tableCellRenderer)
    {
        this.tableCellRenderer = tableCellRenderer;
    }

    public Component getTableCellRendererComponent(JTable table, Object value,
        boolean isSelected, boolean hasFocus, int row, int column)
    {
        Component c = tableCellRenderer.getTableCellRendererComponent(
            table, value, isSelected, hasFocus, row, column);

        if (column == table.getSelectedColumn())
            c.setFont(getFont().deriveFont(Font.BOLD));

        return c;
    }
}

您可以使用如下代码使用渲染器:

JTableHeader header = table.getTableHeader();
DefaultTableCellRenderer defaultRenderer = (DefaultTableCellRenderer)header.getDefaultRenderer();
header.setDefaultRenderer( new MyTableHeaderRenderer(defaultRenderer) );

在您的情况下,您需要更改对齐方式,而不是字体。

您可以使用如下代码:

TableCellRenderer tcr = table.getCellRenderer(0, column);
Component renderer = table.prepareRenderer(tcr, 0, column);
defaultRenderer.setAlignment( renderer.getAlignment() ); // whatever the alignment method is.

编辑:

我所做的不知何故消除了标题的正常格式

您正在使用:

tableColumn.getCellRenderer(); 

如果不是:

tableColumn.getHeaderRenderer();

很少有人会按列为表头指定一个特殊的渲染器。所以如果没有为 TableColumn 指定表头渲染器,你应该使用 JTableHeader 的默认渲染器,不要创建 DefaultTableCellRenderer,这不是表头使用的渲染器。

【讨论】:

  • 嗯,这种方法很有效——无论如何,它可以满足我的要求,但它会改变标题的外观。我正在对问题进行编辑,看看您是否有任何快速建议。
  • @arcy,也许编辑会有所帮助。如果没有,请发布适当的SSCCE 来证明问题。
【解决方案2】:

在我终于明白了这一点之前,我一直在胡思乱想;不知何故,布尔的默认渲染器不是 DefaultTableCellRenderer,所以我无法以这种方式对齐。我尝试将组件放在第一行并进行 ITS 对齐,但如果表中没有数据,则会失败。这对于我现在想要的已经足够了。在我看来,列的对齐必须存在于某个地方,我仍然希望我能以某种方式获取它的值,但到目前为止,我所管理的只是一种获取它的方法,如果列数据使用 DefaultTableCellRenderer。

感谢 camickr 和 MadProgrammer 先生。

import java.awt.Component;

import javax.swing.JTable;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;

/**
 * Renderer that aligns the table's column header with the column's data;
 * if the renderer for the first row of the column data cannot be cast to
 * DefaultTableCellRenderer, this just sets the alignment to CENTER.
 * <P>Use:
 * <pre>
 *      // set our own default renderer for the headers
        JTableHeader header = table.getTableHeader();
        try 
        { DefaultTableCellRenderer defaultRenderer = (DefaultTableCellRenderer)header.getDefaultRenderer();
            header.setDefaultRenderer(new TableHeaderRenderer(defaultRenderer));
        }
        catch (ClassCastException e)
        {
            System.err.println("Could not cast default renderer; table headers not aligned");
        }
 *
 */
@SuppressWarnings("serial")
public class TableHeaderRenderer extends DefaultTableCellRenderer implements TableCellRenderer
{
    DefaultTableCellRenderer innerRenderer = null;

    public TableHeaderRenderer(TableCellRenderer givenRenderer)
    {
        // save the given renderer, normally the default for the header
        innerRenderer = (DefaultTableCellRenderer)givenRenderer;
    }

    @Override
    public Component getTableCellRendererComponent
    (JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
    {
        try
            {
                // get the renderer for the first row
                DefaultTableCellRenderer firstRowTableCellRenderer = (DefaultTableCellRenderer)table.getCellRenderer(0, column);
                int firstRowAlignment = firstRowTableCellRenderer.getHorizontalAlignment();
                // set the alignment of this header to that of the first row
                innerRenderer.setHorizontalAlignment(firstRowAlignment);
                return innerRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, firstRowAlignment, column);
            }
        catch (ClassCastException cce)
        {
          // the first row has a renderer that isn't a DefaultTableCellRenderer
          // just set the alignment to CENTER
            innerRenderer.setHorizontalAlignment(SwingConstants.CENTER);
          return innerRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
        }
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-26
    • 2016-04-28
    • 2011-09-28
    • 1970-01-01
    • 2014-05-27
    • 1970-01-01
    • 2011-03-28
    • 2020-10-22
    相关资源
    最近更新 更多