Я просмотрел ряд вопросов / ответов по настройке выравнивания заголовка JTable, но, похоже, они не охватывают этот случай. Я хочу, чтобы мои заголовки JTable имели такое же выравнивание, как и данные под ними; Мне кажется странным, что все они расположены по центру, особенно для столбцов, в которых есть место для случайных длинных строк, но часто они содержат только короткие строки - заголовок сам по себе находится в центре пространства.

Многие из решений, которые я видел, зависят от DefaultCellTableRenderer - это все заголовки таблиц? Я не хочу устанавливать средство визуализации по умолчанию , поскольку это изменит все столбцы; Я хочу написать код, чтобы вычислить горизонтальное выравнивание данных в столбце, и настроить заголовок так, чтобы он делал то же самое с точки зрения горизонтального выравнивания.

Должен ли я получать компонент из средства визуализации (используя определенную строку, столбец и значение) и устанавливать выравнивание компонента? Должен ли я писать специальный рендерер для заголовка только для этого? Какой самый чистый общий подход?

-- редактировать

Решение мистера Камика элегантно и делает почти то, что я хочу; он перехватывает создание средства визуализации ячейки таблицы для заголовка столбца. Каким-то образом то, что я сделал, устраняет обычное форматирование для заголовка - в моих заголовках нет затенения и границы (хотя они выровнены так, как я хотел!).

В настоящее время у меня есть следующее: где мне взять средство визуализации для заголовка таблицы, как оно есть, чтобы я мог просто изменить выравнивание на нем?

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

Вы можете видеть проблему заголовка, о которой я говорю; Я надеялся, что целые числа по умолчанию будут выровнены по правому краю, но по какой-то причине это не так. Но вы можете увидеть мою проблему только из этого.

1
arcy 26 Окт 2015 в 23:55

2 ответа

Лучший ответ

Вот пример настраиваемого средства визуализации заголовков, которое просто делает текст выбранного столбца жирным:

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, это НЕ средство визуализации, используемое заголовком таблицы.

2
camickr 27 Окт 2015 в 19:50

Я искал, пока наконец не наткнулся на это; каким-то образом средство визуализации по умолчанию для Boolean не является DefaultTableCellRenderer, поэтому я не могу получить его выравнивание таким образом. Я попытался получить компонент в первой строке и получить его выравнивание, но это не удалось, если в таблице нет данных. Этого достаточно для того, что я хочу сейчас. Мне кажется, что выравнивание столбца должно где-то существовать, и я все еще хотел бы получить его значение каким-то образом, но пока все, что мне удалось, - это способ получить его, если данные столбца используют 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);
        }
    }

}
0
arcy 28 Окт 2015 в 12:15