JTable Право Выровнять Заголовок

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

Спасибо

Ответы на вопрос(12)

не держитесь за ссылку на них.

Если вы (или ваши пользователи) используете классическую тему Windows в Windows 7 и вашем приложенииустанавливает систему по умолчанию LAF, ответ отправленный @trashgod может вызвать проблемы для вас.

Это зависит отэта ошибка, опубликованный десять лет назад (серьезно). Если ваша таблица показывается, и вы переключаете тему в настройках Windows с Aero Theme на Windows Classic, там будет множество NPE. Вы НЕ должны удерживать ссылку на средство визуализации, поскольку оно может стать недействительным в определенный момент времени. Обтекание должно выполняться динамически, как это предлагается в комментариях к отчету об ошибках. Я взял оттуда код и создал следующий исполняемый пример:

import java.awt.*;
import java.lang.ref.WeakReference;
import javax.swing.*;
import javax.swing.table.*;

public class TestFrame extends JFrame {

    private static final boolean I_WANT_THE_BUG_TO_HAPPEN = true;

    public static void main(String[] args) throws IllegalAccessException, ClassNotFoundException, InstantiationException, UnsupportedLookAndFeelException {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                int res = JOptionPane.showConfirmDialog(null, "Do you want to use the XP L&F?", "laffo", JOptionPane.YES_NO_OPTION);
                if (res == JOptionPane.YES_OPTION) {
                    try {
                        UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
                    } catch (Exception ex) {
                    }
                }
                new TestFrame().setVisible(true);
            }

        });

    }

    public class MyModel extends AbstractTableModel {

        public int getRowCount() {
            return 10;
        }

        public int getColumnCount() {
            return 10;
        }

        public Object getValueAt(int rowIndex, int columnIndex) {
            return "" + rowIndex + " X " + columnIndex;
        }

    }

    public class MyJTable extends JTable {

        /**
         *
         */
        private static final long serialVersionUID = -233098459210523146L;

        public MyJTable(TableModel model) {
            super(model);
        }

        public void doSomething() {
            System.out.println("HEHE");
        }
    }

    public class MyAlternativeJTable extends JTable {

        private WeakReference<TableCellRenderer> wrappedHeaderRendererRef = null;
        private TableCellRenderer wrapperHeaderRenderer = null;

        public MyAlternativeJTable(TableModel model) {
            super(model);
        }

        private class MyAlternativeTableColumn extends TableColumn {

            MyAlternativeTableColumn(int modelIndex) {
                super(modelIndex);
            }

            @Override
            public TableCellRenderer getHeaderRenderer() {
                TableCellRenderer defaultHeaderRenderer
                        = MyAlternativeJTable.this.getTableHeader().getDefaultRenderer();
                if (wrappedHeaderRendererRef == null
                        || wrappedHeaderRendererRef.get() != defaultHeaderRenderer) {
                    wrappedHeaderRendererRef
                            = new WeakReference<TableCellRenderer>(defaultHeaderRenderer);
                    wrapperHeaderRenderer
                            = new DecoratedHeaderRenderer(defaultHeaderRenderer);
                }
                return wrapperHeaderRenderer;
            }
        }

        @Override
        public void createDefaultColumnsFromModel() {
            TableModel m = getModel();
            if (m != null) {
                // Remove any current columns
                TableColumnModel cm = getColumnModel();
                while (cm.getColumnCount() > 0) {
                    cm.removeColumn(cm.getColumn(0));
                }

                // Create new columns from the data model info
                for (int i = 0; i < m.getColumnCount(); i++) {
                    TableColumn newColumn = new MyAlternativeTableColumn(i);
                    addColumn(newColumn);
                }
            }
        }
    }

    private JPanel jContentPane = null;
    private JScrollPane jScrollPane = null;
    private JTable table1 = null;
    private JScrollPane jScrollPane1 = null;
    private JTable table2 = null;

    /**
     * This is the default constructor
     */
    public TestFrame() {
        super();
        initialize();
        int res = JOptionPane.showConfirmDialog(null, "Do you want to call updateUI() on the tables ?", "laffo", JOptionPane.YES_NO_OPTION);
        if (res == JOptionPane.YES_OPTION) {
            table2.updateUI();
            table1.updateUI();
        }
    }

    /**
     * This method initializes this
     *
     * @return void
     */
    private void initialize() {
        this.setSize(753, 658);
        this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        this.setContentPane(getJContentPane());
        this.setTitle("JFrame");
    }

    /**
     * This method initializes jContentPane
     *
     * @return javax.swing.JPanel
     */
    private JPanel getJContentPane() {
        if (jContentPane == null) {
            jContentPane = new JPanel();
            jContentPane.setLayout(null);
            jContentPane.add(getJScrollPane(), null);
            jContentPane.add(getJScrollPane1(), null);
        }
        return jContentPane;
    }

    /**
     * This method initializes jScrollPane
     *
     * @return javax.swing.JScrollPane
     */
    private JScrollPane getJScrollPane() {
        if (jScrollPane == null) {
            jScrollPane = new JScrollPane();
            jScrollPane.setBounds(new java.awt.Rectangle(358, 0, 387, 618));
            jScrollPane.setViewportView(getTable1());
        }
        return jScrollPane;
    }

    /**
     * This method initializes table1
     *
     * @return javax.swing.JTable
     */
    private JTable getTable1() {
        if (table1 == null) {
            table1 = new JTable(new MyModel());
        }
        return table1;
    }

    /**
     * This method initializes jScrollPane1
     *
     * @return javax.swing.JScrollPane
     */
    private JScrollPane getJScrollPane1() {
        if (jScrollPane1 == null) {
            jScrollPane1 = new JScrollPane();
            jScrollPane1.setBounds(new java.awt.Rectangle(0, 0, 350, 618));
            jScrollPane1.setViewportView(getTable2());
        }
        return jScrollPane1;
    }

    /**
     * This method initializes table2
     *
     * @return javax.swing.JTable
     */
    private JTable getTable2() {
        if (table2 == null) {
            if (I_WANT_THE_BUG_TO_HAPPEN) {
                table2 = new MyJTable(new MyModel());
                JTableHeader header = table2.getTableHeader();
                TableCellRenderer render = new DecoratedHeaderRenderer(header.getDefaultRenderer());
                header.setDefaultRenderer(render);
            } else {
                table2 = new MyAlternativeJTable(new MyModel());
            }
        }
        return table2;
    }

    private class DecoratedHeaderRenderer implements TableCellRenderer {

        public DecoratedHeaderRenderer(TableCellRenderer render) {
            this.render = render;
        }
        private TableCellRenderer render;

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

    }

}

Просто запустите пример и выберитеYes дважды и смотреть, как он разваливается. Затем изменитеI_WANT_THE_BUG_TO_HAPPEN статический членfalse и повтори. Случай с этим членом установлен вtrue по сути такой же, как и самый одобренный ответ здесь. Наиболее важной частью этого примера является расширенныйJTable (MyAlternativeJTable) который делает обтекание динамически.

В настоящее время принятый ответ на этот вопрос широко используется, но это не рекомендуется. Вы можете воспроизвести его с потерянными приложениями, включая Netbeans 8.0.2 (который сам основан на Java), пока он показывает сортируемую таблицу, такую какWindow > IDE Tools > Notificationsгде вы также получите отчеты NPE, по иронии судьбы. Просто переключите тему Windows с Aero на Windows Classic (черезright-click Desktop > Personalize > Change the visuals and sounds on your computer) на Windows 7.

Если вы используете Glazed Lists и звонитеca.odell.glazedlists.swing.TableComparatorChooser.install, вы также затронуты. Он внедряет свой собственный рендер для сортировки стрелок.

Я наткнулся на это случайно, пытаясь найти решение дляэтот вопрос я подозреваю, что это связано

 kmort21 июн. 2016 г., 17:48
Отлично сработано. Жаль, что я не мог бы голосовать за это больше раз.
  ((DefaultTableCellRenderer)jTable2.getTableHeader().getDefaultRenderer())
    .setHorizontalAlignment(JLabel.CENTER);
 yanman123407 авг. 2017 г., 19:32
Это не ответ на вопрос. Вы должны пересмотреть это, чтобы включить объяснение того, как или почему это решает заданный вопрос, чтобы другие могли узнать и понять, как применить это к своим собственным проблемам.

JTableHeader jtableHeader = jtable.getTableHeader();
DefaultTableCellRenderer rend = (DefaultTableCellRenderer) jtable.getTableHeader().getDefaultRenderer();
rend.setHorizontalAlignment(JLabel.CENTER);
jtableHeader.setDefaultRenderer(rend);
 Kannan Arumugam08 нояб. 2013 г., 08:46
да, извините за это ...
 kleopatra18 сент. 2013 г., 09:50
хм ... ничего нового по сравнению с более ранними ответами, не так ли ;-) Кстати: нет необходимости устанавливать стандартный рендерер снова, этоуже есть средство визуализации по умолчанию
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) your_jtable.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(0);

0 Центр.

 SingleShot17 апр. 2013 г., 01:20
Вместо0 Я предлагаюSwingConstants.CENTER.
for (int i = 0 ; i < table.getColumnCount(); i++){

    DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
    renderer.setHorizontalAlignment(SwingConstants.RIGHT);
    table.getColumn(i).setHeaderRenderer(renderer);

}
 trashgod21 сент. 2011 г., 04:04
Кажется более надежным установить выравнивание на существующем рендере, чем пытаться украсить новый. (Не гуру; просто попутчик.)
 Drew Galbraith21 сент. 2011 г., 03:03
Это то, что у меня было изначально, но, к сожалению, это отвергает внешний вид заголовков. Также вы должны использовать классDefaultTableCellRenderer для объекта визуализации, потому чтоTableCellRenderer не имеет методаsetHorizontalAlighment
 Kevin Reid21 сент. 2011 г., 03:15
Это клудж, но, возможно, вы могли бы получить существующий рендер и сделать экземпляр и привести кDefaultTableCellRenderer перед установкой выравнивания? Или, может быть, есть способ заставить новый () в правильном L & F?
 Heisenbug21 сент. 2011 г., 03:24
На самом деле я был неправ. Я не знаю лучшего способа сделать это. Может быть, @Kevin Reid прав. Давайте подождем и посмотрим, сможет ли какой-нибудь гуру свинга рассказать нам об этом подробнее.
 trashgod21 сент. 2011 г., 13:44
+1 за критическое изучение подхода. @mKorbel: я чувствую, что мывсе ученики клеопатры. :-)

показанный выше (2011 / sep / 21 by trashgod) в сочетании с кодом из Heisenbug (2011 / sep / 21), будет работать правильно, только если все заголовки выровнены одинаково.

Если вы хотите выровнять разные заголовки по-разному, вам придется использовать следующий код:

int[] alignments = new int[] { JLabel.LEFT, JLabel.RIGHT, JLabel.RIGHT };
for (int i = 0 ; i < jTable.getColumnCount(); i++){
  jTable.getTableHeader().getColumnModel().getColumn(i)
    .set(new (jTable, alignments[i]));
}

а также

private static class  implements TableCellRenderer {
  DefaultTableCellRenderer renderer;
  int horAlignment;
  public (JTable table, int horizontalAlignment) {
    horAlignment = horizontalAlignment;
    renderer = (DefaultTableCellRenderer)table.getTableHeader()
        .getDefaultRenderer();
  }
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int col) {
    Component c = renderer.getTableCellRendererComponent(table, value,
      isSelected, hasFocus, row, col);
    JLabel label = (JLabel)c;
    label.setHorizontalAlignment(horAlignment);
    return label;
  }
}

Это:
Установите выравнивание вgetTableCellRendererComponent и не в конструктор.

чтобы использовать средство визуализации из фиктивной таблицы, чтобы получить правильные L & F, и скопировать выравнивание из средства визуализации строк реальной таблицы. Таким образом, каждый столбец выравнивается отдельно. Вот код:

table.getTableHeader().setDefaultRenderer(new DefaultTableCellRenderer() {
    @Override
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
        Component c2 = dummy.getTableHeader().getDefaultRenderer().getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
        if (table.getRowCount() > 0) {
            Component c3 = table.getCellRenderer(0, col).getTableCellRendererComponent(table, value, isSelected, hasFocus, 0, col);
            if (c2 instanceof JLabel && c3 instanceof JLabel)
                ((JLabel)c2).setHorizontalAlignment(((JLabel)c3).getHorizontalAlignment());
        }
        return c2;
    }
    private final JTable dummy = new JTable();
});

Приведенный выше код не сохраняет никаких ссылок на средства визуализации, поэтому он позволяет избежать ошибки NPE, упомянутой выше. Для этого не требуется никакого именованного класса, поэтому вы можете просто вставить код туда, где он вам нужен.

Решение Вопроса

TableCellRenderer столаJTableHeader, Это не обязательно для этого использования, но это минимизирует влияние на внешний вид делегата пользовательского интерфейса.

Типичное использование:

JTable table = new JTable(…);
JTableHeader header = table.getTableHeader();
header.setDefaultRenderer(new HeaderRenderer(table));

Пользовательский заголовок рендерера:

private static class HeaderRenderer implements TableCellRenderer {

    DefaultTableCellRenderer renderer;

    public HeaderRenderer(JTable table) {
        renderer = (DefaultTableCellRenderer)
            table.getTableHeader().getDefaultRenderer();
        renderer.setHorizontalAlignment(JLabel.CENTER);
    }

    @Override
    public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected,
        boolean hasFocus, int row, int col) {
        return renderer.getTableCellRendererComponent(
            table, value, isSelected, hasFocus, row, col);
    }
}
 Farkas Csanád10 нояб. 2014 г., 14:04
просто небольшая проблема, я думаю, что это малоН] eader header.setDefaultRenderer(new HeaderRenderer(table)); Кстати, я тоже искал это решение, и оно отлично работает. Единственное, что мне нужно, чтобы изменить этот капиталH до ч.
 trashgod22 сент. 2011 г., 02:07
 Heisenbug21 сент. 2011 г., 12:10
+1. Это правильное решение. Вчера я немного устал и ничего не придумал :). Установка нового рендерера не была хорошей идеей.

((DefaultTableCellRenderer)table.getTableHeader().getDefaultRenderer())
    .setHorizontalAlignment(JLabel.RIGHT);
 Heisenbug21 сент. 2011 г., 02:50
ОП запрашивает заголовок, а не ячейки.
 Drew Galbraith21 сент. 2011 г., 05:28
TableCellRenderer не имеет методаsetHorizontalAlignment() :(
 trashgod21 сент. 2011 г., 03:59
+1JTableHeader используетTableCellRenderer; setHorizontalAlignment() работать правильно в этом связанномпример.
 trashgod21 сент. 2011 г., 06:07
К сожалению, я упустил необходимость приведения средства визуализации заголовка таблицы; Код обновлен.
 kleopatra21 сент. 2011 г., 08:39
не нужно зацикливаться - заголовок имеет толькоодин рендерер по умолчанию :-)

основанный на решении pvbemmelen62, который можно использовать очень легко, например:

AlignHeaderRenderer.install(myTable, new int[] { SwingConstants.RIGHT,
                        SwingConstants.RIGHT, SwingConstants.LEFT });

или же

AlignHeaderRenderer.install(myTable, 0, SwingConstants.RIGHT);
AlignHeaderRenderer.install(myTable, 1, SwingConstants.RIGHT);

Вот код:

public class AlignHeaderRenderer implements TableCellRenderer {

private final TableCellRenderer renderer;
private final int alignment;

public static void install(final JTable table, final int[] alignments) {
    for (int i = 0; i < alignments.length; ++i)
        install(table, i, alignments[i]);
}

public static void install(final JTable table, final int row,
        final int alignment) {
    table.getTableHeader().getColumnModel().getColumn(row)
            .setHeaderRenderer(new AlignHeaderRenderer(table, alignment));
}

private AlignHeaderRenderer(final JTable table, final int alignment) {
    renderer = table.getTableHeader().getDefaultRenderer();
    this.alignment = alignment;
}

@Override
public Component getTableCellRendererComponent(final JTable table,
        final Object value, final boolean isSelected,
        final boolean hasFocus, final int row, final int col) {
    final Component c = renderer.getTableCellRendererComponent(table,
            value, isSelected, hasFocus, row, col);
    ((JLabel) c).setHorizontalAlignment(alignment);
    return c;
}

}
((JLabel)mTabBOM.getTableHeader().getDefaultRenderer()).setHorizontalAlignment( JLabel.CENTER );
 Elliott Frisch20 июл. 2014 г., 05:46
Не могли бы вы объяснить, для чего предназначена эта строка кода и почему? Например, как «CENTER» выровнен по правому краю?
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) 
MSISDNTable.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(JLabel.RIGHT);

MSISDNTable твой стол

Ваш ответ на вопрос