Подтвердить что ты не робот

JTable Right Align Header

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

Спасибо

4b9b3361

Ответ 1

Здесь альтернативный подход к изменению 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);
    }
}

Ответ 2

Попробуйте следующее:

((DefaultTableCellRenderer)table.getTableHeader().getDefaultRenderer())
    .setHorizontalAlignment(JLabel.RIGHT);

Ответ 3

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.

Ответ 4

DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) your_jtable.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(0);

Где 0 находится Центр.

Ответ 5

for (int i = 0 ; i < table.getColumnCount(); i++){

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

}

Ответ 6

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

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

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

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

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

Ответ 7

DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) 
MSISDNTable.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(JLabel.RIGHT);

где MSISDNTable - ваша таблица

Ответ 8

Попробуйте этот код,

JTableHeader jtableHeader = jtable.getTableHeader();
DefaultTableCellRenderer rend = (DefaultTableCellRenderer) jtable.getTableHeader().getDefaultRenderer();
rend.setHorizontalAlignment(JLabel.CENTER);
jtableHeader.setDefaultRenderer(rend);

Ответ 9

Я создал класс на основе решения 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;
}

}

Ответ 10

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

Ответ 11

  ((DefaultTableCellRenderer)jTable2.getTableHeader().getDefaultRenderer())
    .setHorizontalAlignment(JLabel.CENTER);

Ответ 12

((JLabel)mTabBOM.getTableHeader().getDefaultRenderer()).setHorizontalAlignment( JLabel.CENTER );