JTable Право Выровнять Заголовок - PullRequest
25 голосов
/ 21 сентября 2011

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

Спасибо

Ответы [ 12 ]

43 голосов
/ 21 сентября 2011

Вот альтернативный подход к изменению 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);
    }
}
36 голосов
/ 21 сентября 2011

Попробуйте это:

((DefaultTableCellRenderer)table.getTableHeader().getDefaultRenderer())
    .setHorizontalAlignment(JLabel.RIGHT);
5 голосов
/ 22 февраля 2013
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) your_jtable.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(0);

Где 0 - Центр.

4 голосов
/ 15 ноября 2012

HeaderRenderer, показанный выше (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)
    .setHeaderRenderer(new HeaderRenderer(jTable, alignments[i]));
}

и

private static class HeaderRenderer implements TableCellRenderer {
  DefaultTableCellRenderer renderer;
  int horAlignment;
  public HeaderRenderer(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, а не в конструкторе HeaderRenderer.

2 голосов
/ 20 апреля 2016

Следует помнить об обёртывании заголовков таблиц по умолчанию: не держитесь за ссылку на них.

Если вы (или ваши пользователи) используете тему Windows Classic в 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, это также влияет на вас. Он внедряет свой собственный рендерер для сортировки стрелок.

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

2 голосов
/ 01 декабря 2015
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) 
MSISDNTable.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(JLabel.RIGHT);

где MSISDNTable ваш стол

2 голосов
/ 21 сентября 2011
for (int i = 0 ; i < table.getColumnCount(); i++){

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

}
0 голосов
/ 07 августа 2017
  ((DefaultTableCellRenderer)jTable2.getTableHeader().getDefaultRenderer())
    .setHorizontalAlignment(JLabel.CENTER);
0 голосов
/ 03 марта 2017

Секрет в том, чтобы использовать средство рендеринга из фиктивной таблицы, чтобы получить правильный 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, упомянутой выше.Он не требует никакого именованного класса, поэтому вы можете просто вставить код туда, где он вам нужен.

0 голосов
/ 20 июля 2014
((JLabel)mTabBOM.getTableHeader().getDefaultRenderer()).setHorizontalAlignment( JLabel.CENTER );
...