java - titulo - JTable derecha Alinear encabezado
jtable java netbeans (12)
Básicamente, tengo una JTable que contiene columnas con celdas alineadas a la derecha pero encabezados a la izquierda que lucen realmente mal. Me gustaría alinear a la derecha los encabezados de estas columnas sin alterar el "Look and Feel" de los encabezados.
Gracias
Algo que hay que recordar sobre cómo envolver encabezados de tabla predeterminados: no retener una referencia de ellos.
Si usted (o sus usuarios) están utilizando un tema clásico de Windows en Windows 7 y su aplicación establece LAF predeterminada del sistema , la respuesta publicada por @trashgod puede causarle problemas.
Se ve afectado por este error , publicado hace una década (en serio). Si su tabla se muestra y cambia el tema en las preferencias de Windows de un tema Aero a Windows Classic, habrá una avalancha de NPE. NO se supone que tengas que retener una referencia de un renderizador ya que puede volverse inválida en algún momento. La envoltura debe hacerse de una manera dinámica, como se sugiere en los comentarios del informe de errores. Tomé el código desde allí y creé el siguiente ejemplo ejecutable:
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;
}
}
}
Simplemente ejecute el ejemplo y elija Yes
dos veces para ver cómo se rompe. A continuación, cambie el miembro estático I_WANT_THE_BUG_TO_HAPPEN
a false
y repita. El caso con este miembro configurado como true
es esencialmente el mismo que la respuesta más votada aquí. La parte más importante de este ejemplo es la JTable
extendida ( MyAlternativeJTable
) que realiza el MyAlternativeJTable
forma dinámica.
La respuesta actualmente aceptada a esta pregunta es ampliamente utilizada, pero no es aconsejable. Puede reproducirlo con la pérdida de aplicaciones, incluido Netbeans 8.0.2 (que a su vez está basado en Java) mientras muestra una tabla ordenable, como Window > IDE Tools > Notifications
, donde también obtendrá los informes NPE, irónicamente. Simplemente cambie el tema de Windows de Aero a Windows Classic (mediante right-click Desktop > Personalize > Change the visuals and sounds on your computer
) en Windows 7.
Si usa Glazed Lists y llama a ca.odell.glazedlists.swing.TableComparatorChooser.install
, también se verá afectado. Inyecta su propio procesador personalizado para ordenar flechas.
Me tropecé con esto por coincidencia al tratar de encontrar una solución para esta pregunta que sospecho que está relacionada.
Creé una clase basada en la solución de pvbemmelen62, que se puede usar muy fácilmente, por ejemplo:
AlignHeaderRenderer.install(myTable, new int[] { SwingConstants.RIGHT,
SwingConstants.RIGHT, SwingConstants.LEFT });
o
AlignHeaderRenderer.install(myTable, 0, SwingConstants.RIGHT);
AlignHeaderRenderer.install(myTable, 1, SwingConstants.RIGHT);
Aquí está el código:
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;
}
}
El HeaderRenderer mostrado arriba (2011 / sep / 21 por trashgod) combinado con el código de Heisenbug (2011 / sep / 21), solo funcionará correctamente si tiene todos los encabezados alineados de la misma manera.
Si desea alinear diferentes encabezados de manera diferente, tendrá que usar el siguiente código:
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]));
}
y
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;
}
}
Es decir:
Establezca la alineación en getTableCellRendererComponent
, y no en el constructor HeaderRenderer
.
El secreto es usar el renderizador de una tabla ficticia para obtener L y F correctos, y copiar la alineación del renderizador de filas de la tabla real. De esa forma, cada columna se alinea por separado. Aquí está el código:
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();
});
El código anterior no conserva ninguna referencia a los procesadores, por lo que evita el error de NPE mencionado anteriormente. No requiere ninguna clase con nombre, por lo que puede simplemente colocar el código donde lo necesite.
Prueba este código,
JTableHeader jtableHeader = jtable.getTableHeader();
DefaultTableCellRenderer rend = (DefaultTableCellRenderer) jtable.getTableHeader().getDefaultRenderer();
rend.setHorizontalAlignment(JLabel.CENTER);
jtableHeader.setDefaultRenderer(rend);
Prueba esto:
((DefaultTableCellRenderer)table.getTableHeader().getDefaultRenderer())
.setHorizontalAlignment(JLabel.RIGHT);
Aquí hay un enfoque alternativo para modificar el TableCellRenderer
del TableCellRenderer
de una tabla. No es estrictamente necesario para este uso, pero minimiza el impacto en la apariencia del delegado de UI.
Uso típico:
JTable table = new JTable(…);
JTableHeader header = table.getTableHeader();
header.setDefaultRenderer(new HeaderRenderer(table));
Renderizador de encabezado personalizado:
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);
}
}
((DefaultTableCellRenderer)jTable2.getTableHeader().getDefaultRenderer())
.setHorizontalAlignment(JLabel.CENTER);
((JLabel)mTabBOM.getTableHeader().getDefaultRenderer()).setHorizontalAlignment( JLabel.CENTER );
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)
MSISDNTable.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(JLabel.RIGHT);
donde MSISDNTable
es tu mesa
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) your_jtable.getTableHeader().getDefaultRenderer();
renderer.setHorizontalAlignment(0);
Donde 0
es el centro
for (int i = 0 ; i < table.getColumnCount(); i++){
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
renderer.setHorizontalAlignment(SwingConstants.RIGHT);
table.getColumn(i).setHeaderRenderer(renderer);
}