JTable con JButton (Swing)

Resuelto
Hola a todos,

En el marco de un proyecto personal, estoy utilizando JTable pero tengo un problema importante con la selección de una fila.

Una imagen vale más que mil palabras, así que aquí está la imagen de mi JTable.



Como pueden ver en la imagen, cuando se selecciona una fila, solo las columnas "String" tienen el fondo azul/gris y las columnas "JButton" no lo tienen. Sin embargo, realmente me gustaría que todas las columnas tuvieran el fondo azul/gris cuando se selecciona una fila.

He probado muchas cosas, pero nada lo que he hecho hasta ahora ha resuelto el problema.

 addMouseListener(new TableMouseListener(this)); setDefaultRenderer(Object.class, new TableCellRenderer()); setSelectionMode(ListSelectionModel.SINGLE_SELECTION); setRowHeight(25); 


 public class TableCellRenderer extends DefaultTableCellRenderer { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); setBorder(BorderFactory.createEmptyBorder(0, 3, 2, 0)); setFont(getFont().deriveFont(14f)); if(value instanceof Button) { return (Button) value; } return this; } } 


Si alguien también tiene consejos para hacer la JTable más atractiva estéticamente, estaré encantado de escucharlos ^^

Gracias por su ayuda,

Mikis

3 respuestas

  1. Moderador
    Hola,

    El problema es que tu botón ocupa todo el tamaño de la celda, por lo que no deja traslucir el fondo de la fila que cambia de color.

    Podrías utilizar el parámetro isSelected para identificar cuándo la fila está seleccionada y cambiar el color de fondo del botón en consecuencia.

    Ejemplo:

    import java.awt.*; import javax.swing.*; import javax.swing.table.DefaultTableCellRenderer; public class Test { public static void main(String[] args) { Object[][] rowData = { { "a1", "b1", new JButton("c1") }, { "a2", "b2", new JButton("c2") } }; String[] numColumns = { "a", "b", "c" }; JTable table = new JTable(rowData, numColumns); table.setSelectionBackground(Color.YELLOW); table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() { @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { if (value instanceof JButton) { JButton button = (JButton) value; button.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground()); return button; } else { return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); } } }); JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.add(table); frame.pack(); frame.setVisible(true); } }
    La confianza no excluye el control.
    1
    1. Bueno, después de lo que me dijiste:

      "Así que el problema puede venir de la forma en que codificaste esta clase"

      Fui a ver la clase en cuestión y aquí está el código que había:

       public Button(String icon, ActionListener action) { super(new ImageIcon("icons" + File.separator + icon)); addActionListener(action); setBorderPainted(false); setBorder(null); setBackground(null); setMargin(new Insets(0, 0, 0, 0)); setContentAreaFilled(false); } 


      El problema era entonces el setContentAreaFilled(false) que había puesto para no tener un cambio de color al hacer clic en un botón. Desafortunadamente, el resultado en las JTable no era muy bueno ya que los botones no tenían fondo.

      Así que reemplacé el código anterior por este

       public Button(String icon, ActionListener action) { super(new ImageIcon("icons" + File.separator + icon)); addActionListener(action); setBorderPainted(false); setBorder(null); setBackground(null); setMargin(new Insets(0, 0, 0, 0)); addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { ((JButton) e.getSource()).setContentAreaFilled(false); } }); } 


      Y sin saber por qué, ahora funciona muy bien.
      En las tablas el resultado es excelente y cuando hago clic en un botón, no hay cambio de color.



      ¡Gracias de todos modos!
      1
      1. "El problema es que tu botón ocupa todo el tamaño de la celda, por lo que ya no deja traslucir el fondo de la línea que cambia de color."

        Sin embargo, cuando hago un

        table.setBackground(Color.ORANGE);


        Obtengo esto



        E incluso intenté algo para que se vea más bonito. Alternar el color una línea sí y la siguiente no, pero el resultado en los botones sigue siendo "sin color" (el color por defecto de la JTable)



        Creo que hay algo que no he entendido en los Renderer o los Editor que permitiría que aparezca mi botón y el fondo de la celda.
        0
        1. Moderador
          Aquí está la tabla que tú coloreas de naranja, yo hablo de colorear solo el botón, como en mi ejemplo.

          if (value instanceof JButton) { JButton button = (JButton) value; button.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground()); return button; }
          0
        2. @KXNada sucede cuando escribo su código..

          Si tomas la tercera imagen, ¿de dónde crees que proviene el problema? porque los botones no están "coloriendo" una línea sí y otra no..
          0
        3. Moderador
          @mikis69Si has puesto mi código tal cual, es normal que no pase nada, porque en mi ejemplo tomé JButton (Swing), mientras que tú has puesto Button (AWT), así que el instanceof no puede funcionar si no hablamos de la misma clase.

          En la medida en que usas Swing, deberías reemplazar tus Button por JButton.
          0
        4. De hecho, la clase Button que he creado hereda de JButton...
          0
        5. Moderador
          @mikis69Ah... ¿no es la clase Button de java.awt?
          Es una mala idea haberla nombrado como una clase estándar de Java.

          Así que el problema puede venir de la manera en que has codificado esta clase... aunque eso no forma parte de los fragmentos de código que nos has dado.

          Nota: puedes probar el código que puse hace un rato (es un main para ejecutar), verás que funciona muy bien y que el botón está bien resaltado.
           
          0