it-swarm.com.de

JTable Right Align Header

Grundsätzlich habe ich eine JTable mit Spalten mit rechtsbündigen Zellen, aber linksbündigen Kopfzeilen, was wirklich schlecht aussieht. Ich möchte die Kopfzeilen dieser Spalten nach rechts ausrichten, ohne das "Look and Feel" der Kopfzeilen zu verändern.

Vielen Dank

24
Drew Galbraith

Hier ist ein alternativer Ansatz zum Ändern der TableCellRenderer einer JTableHeader einer Tabelle. Dies ist für diese Verwendung nicht unbedingt erforderlich, minimiert jedoch die Auswirkungen auf das Erscheinungsbild des UI-Delegierten.

Typische Verwendung:

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

Benutzerdefinierter Header-Renderer:

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

Versuche dies:

((DefaultTableCellRenderer)table.getTableHeader().getDefaultRenderer())
    .setHorizontalAlignment(JLabel.RIGHT);
35
Eng.Fouad
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) your_jtable.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(0);

Wo 0 ist Center.

5
chathun

Der oben abgebildete HeaderRenderer (2011/sep/21 von trashgod) in Kombination mit dem Code von Heisenbug (2011/sep/21) funktioniert nur dann korrekt, wenn alle Header gleich ausgerichtet sind.

Wenn Sie verschiedene Kopfzeilen unterschiedlich ausrichten möchten, müssen Sie den folgenden Code verwenden:

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

und

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

Das ist:
Stellen Sie die Ausrichtung in getTableCellRendererComponent und nicht im Konstruktor HeaderRenderer ein.

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

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

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

wobei MSISDNTable Ihre Tabelle ist

2
Mahfuz Ahmed

Beachten Sie beim Umschließen von Standard-Tabellenköpfen: Halten Sie sich nicht an einen Verweis davon.

Wenn Sie (oder Ihre Benutzer) ein klassisches Windows-Design unter Windows 7 verwenden und Ihre Anwendung setzt das Standardsystem LAF , die Antwort , die von @trashgod veröffentlicht wird, kann Probleme für Sie verursachen. 

Es ist betroffen von diesem Fehler , der vor einem Jahrzehnt veröffentlicht wurde (ernsthaft). Wenn Ihre Tabelle angezeigt wird und Sie das Design in den Windows-Voreinstellungen von Aero Theme auf Windows Classic umstellen, wird eine Vielzahl von NPEs angezeigt. Sie dürfen sich NICHT an einer Referenz eines Renderers halten, da sie zu einem bestimmten Zeitpunkt ungültig werden kann. Die Verpackung sollte auf dynamische Weise erfolgen, wie in den Kommentaren des Fehlerberichts empfohlen. Ich nahm den Code von dort und erstellte das folgende ausführbare Beispiel:

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

    }

}

Führen Sie einfach das Beispiel aus und wählen Sie zweimal Yes. Ändern Sie dann den statischen Member I_WANT_THE_BUG_TO_HAPPEN in false und wiederholen Sie den Vorgang. Der Fall, bei dem dieses Mitglied auf true gesetzt ist, stimmt im Wesentlichen mit der hier am häufigsten bewerteten Antwort überein. Der wichtigste Teil dieses Beispiels ist die erweiterte JTable (MyAlternativeJTable), die das Wrapping dynamisch ausführt.

Die derzeit akzeptierte Antwort auf diese Frage ist weit verbreitet, wird jedoch schlecht beraten. Sie können es mit verlorenen Anwendungen reproduzieren, einschließlich Netbeans 8.0.2 (das selbst Java-basiert), während eine sortierbare Tabelle angezeigt wird, z. B. Window > IDE Tools > Notifications, in der Sie ironischerweise auch die NPE-Berichte erhalten. Wechseln Sie unter Windows 7 einfach das Windows-Design von Aero zu Windows Classic (über right-click Desktop > Personalize > Change the visuals and sounds on your computer).

Wenn Sie verglaste Listen verwenden und ca.odell.glazedlists.swing.TableComparatorChooser.install aufrufen, sind Sie ebenfalls betroffen. Es enthält einen eigenen benutzerdefinierten Renderer zum Sortieren von Pfeilen.

Ich bin zufällig darauf gestoßen, als ich versuchte, eine Lösung für diese Frage zu finden, von der ich vermute, dass sie damit zusammenhängt.

2
predi

Das Geheimnis besteht darin, den Renderer aus einer Dummy-Tabelle zu verwenden, um korrekte L & F-Werte zu erhalten, und die Ausrichtung aus dem Zeilen-Renderer der realen Tabelle kopieren. So wird jede Spalte separat ausgerichtet. Hier ist der Code:

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

Der obige Code enthält keine Verweise auf Renderer, sodass der oben genannte NPE-Fehler vermieden wird. Es ist keine benannte Klasse erforderlich, sodass Sie den Code einfach dort ablegen können, wo Sie ihn benötigen.

0
Adam Gawne-Cain

Versuchen Sie diesen Code,

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

Ich habe eine Klasse basierend auf der Lösung von pvbemmelen62 erstellt, die sehr einfach verwendet werden kann, zum Beispiel:

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

oder

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

Hier ist der Code:

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

}
0
Oliver Hoffmann