2010-07-06 18 views
7

Usar un color de fondo diferente para las filas pares e impares es un truco comúnmente utilizado para mejorar la legibilidad de las tablas grandes.J Mesa con fondo de rayas

Quiero usar este efecto en la JTable de Swing. Empecé creando un renderizador de tabla personalizado, pero esto solo se puede usar para pintar las celdas reales, y también quiero agregar rayas a la parte "blanca" de la tabla donde no podría haber celdas. Puedo subclasificar a JTable y reemplazar paintComponent(), pero preferiría una opción donde simplemente pueda cambiar la representación de la tabla.

¿Hay una mejor manera de hacerlo?

Editar: De acuerdo con las respuestas hasta ahora esto parece ser imposible sin extender JTable. Sin embargo, cuando anulo JTable.paintComponent() también solo pinta el área donde hay filas. ¿Cómo puedo pintar el resto?

+0

¿Por qué? Si una tabla tiene solo 5 líneas de datos y desea pintar 100, simplemente agregue 95 líneas de datos en blanco. Utilice un ciclo 'for' 95 veces a' model.addRow (new Object [] {}); '. El área en blanco pertenece al JScrollPane debajo, no a la tabla, porque sin un límite, no sabemos dónde parar. JTable detiene el procesamiento cuando no hay datos. Esa es la lógica. – FaithReaper

Respuesta

4

Usa getCellRect(getRowCount() - 1, 0, true).y para obtener la coordenada y superior del espacio vacío, y luego pinta algunos rectángulos y líneas (Cuadrícula) con paintComponent(Graphics g).

jtable with empty space grid

para que sea mucho más fácil para usted, he aquí una solución a largo (pero completo) ;-)

import java.awt.Color; 
import java.awt.Component; 
import java.awt.Graphics; 
import java.awt.Rectangle; 
import javax.swing.JFrame; 
import javax.swing.JScrollPane; 
import javax.swing.JTable; 
import javax.swing.UIManager; 
import javax.swing.table.TableCellRenderer; 
import javax.swing.table.TableColumn; 

public class StripedEvenInWhitePartsTable extends JTable 
{ 

    public StripedEvenInWhitePartsTable(String[][] data, String[] fields) 
    { 
    super(data, fields); 
    setFillsViewportHeight(true); //to show the empty space of the table 
    } 


    @Override 
    public void paintComponent(Graphics g) 
    { 
    super.paintComponent(g); 

    paintEmptyRows(g); 
    } 


    public void paintEmptyRows(Graphics g) 
    { 
    Graphics newGraphics = g.create(); 
    newGraphics.setColor(UIManager.getColor("Table.gridColor")); 

    Rectangle rectOfLastRow = getCellRect(getRowCount() - 1, 0, true); 
    int firstNonExistentRowY = rectOfLastRow.y; //the top Y-coordinate of the first empty tablerow 

    if (getVisibleRect().height > firstNonExistentRowY) //only paint the grid if empty space is visible 
    { 
     //fill the rows alternating and paint the row-lines: 
     int rowYToDraw = (firstNonExistentRowY - 1) + getRowHeight(); //minus 1 otherwise the first empty row is one pixel to high 
     int actualRow = getRowCount() - 1; //to continue the stripes from the area with table-data 

     while (rowYToDraw < getHeight()) 
     { 
     if (actualRow % 2 == 0) 
     { 
      newGraphics.setColor(Color.ORANGE); //change this to another color (Color.YELLOW, anyone?) to show that only the free space is painted 
      newGraphics.fillRect(0, rowYToDraw, getWidth(), getRowHeight()); 
      newGraphics.setColor(UIManager.getColor("Table.gridColor")); 
     } 

     newGraphics.drawLine(0, rowYToDraw, getWidth(), rowYToDraw); 

     rowYToDraw += getRowHeight(); 
     actualRow++; 
     } 


     //paint the column-lines: 
     int x = 0; 
     for (int i = 0; i < getColumnCount(); i++) 
     { 
     TableColumn column = getColumnModel().getColumn(i); 
     x += column.getWidth(); //add the column width to the x-coordinate 

     newGraphics.drawLine(x - 1, firstNonExistentRowY, x - 1, getHeight()); 
     } 

     newGraphics.dispose(); 

    } //if empty space is visible 

    } //paintEmptyRows 



    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) 
    { 
    Component c = super.prepareRenderer(renderer, row, column); 

    if (!isRowSelected(row)) 
    { 
     c.setBackground(row % 2 == 0 ? getBackground() : Color.ORANGE); 
    } 

    return c; 
    } 


    public static void main(String[] argv) 
    { 
    String data[][] = { { "A0", "B0", "C0" }, { "A1", "B1", "C1" }, { "A2", "B2", "C2" }, { "A3", "B3", "C3" }, { "A4", "B4", "C4" } }; 
    String fields[] = { "A", "B", "C" }; 

    JFrame frame = new JFrame("a JTable with striped empty space"); 
    StripedEvenInWhitePartsTable table = new StripedEvenInWhitePartsTable(data, fields); 
    JScrollPane pane = new JScrollPane(table); 

    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.add(pane); 
    frame.setSize(400, 300); 
    frame.setLocationRelativeTo(null); 
    frame.setVisible(true); 
    } 

} 

Este ejemplo podría extenderse a:

  • fijar el pseudogrid pintado para la variable RowHeights (estoy usando la altura más baja utilizada en cualquier fila)
  • explicar al usuario por qué no sucede nada i si hace clic en el espacio vacío para editar las celdas (mediante la información sobre herramientas)
  • agregue una fila adicional al modelo de la tabla si el usuario hace clic en el espacio vacío (nooo! sin Excel por favor!)
  • utilizan el espacio vacío para dibujar un reflejo de la tabla (incluyendo todos los datos prestados (¿para qué? ;-))
+0

setFillsViewportHeight (verdadero) es lo que me perdí. ¡Gracias! –

+0

Solo quería decir gracias por esta respuesta, tuve que modificar algunas cosas (dos filas del mismo color en la parte superior cuando la tabla está vacía), pero de lejos esta es la mejor solución al problema sin ir a un tercero fuente. Muchas gracias. –

2

El JXtable proporcionada por SwingX le permiten implementa dicha representación Tome un vistazo a http://swinglabs.org/docs/components/JXTable/tutorial.jsp?step=3#RowHighlighting

+0

Disculpe, pero no sé si podría personalizarlo para "agregar rayas a la parte" blanca "de la tabla donde podría no haber celdas". –

+0

Parece una buena solución. Lo comprobaré. –

+1

Sin embargo, los resaltadores están limitados a las celdas. – Gnoupi

0

De cualquier uso JXTable o si se encuentra (o super :-) de corta duración) super perezoso) sólo se puede utilizar "Nimbus" look-and-feel, JTable no se ve despojado por defecto :)

+1

Nimbus solo está cambiando el comportamiento del procesador predeterminado, por lo que no se extenderá fuera de las células también. – Gnoupi

+0

No, he dicho que es muy vago ... Pero el Nimbus se ve mejor para mí, así que estoy completamente cómodo con el predeterminado – Xorty

+0

En el mismo tipo de solución, también puede consultar Sustancia (https: // substance.dev.java.net/) LAF, lo he usado en el pasado y podría configurarlo fácilmente con un fondo despojado. – jfpoilpret

1

también puede utilizar una costumbre TableCellRenderer que escoger el color para usted, con una parte del código como este en el interior:

if (isSelected) //color remains the same while selected 
{ 
    lFgColor = table.getSelectionForeground(); 
    lBgColor = table.getSelectionBackground(); 
} 
else 
{ 
    lFgColor = table.getForeground(); 
    if (row%2 != 0) //once out of two rows, change color 
     lBgColor = table.getBackground(); 
    else 
    { 
     //New look and feels like nimbus declare this property, try to use it 
     lBgColor = UIManager.getColor("Table.alternateRowColor"); 
     if (lBgColor == null) //If not, choose your own color 
      lBgColor = UIManager.getColor("Table.light"); 
     } 
    } 
} 

Editar: Eché de menos el hecho de que ya lo intentó, y que necesita extender este color al espacio sin celdas. Que yo sepa, esto no es posible con la implementación actual de JTable o JXTable. Los resaltadores de JXTable son en su mayoría procesadores sofisticados, todavía atienden solo a las células.

Para ampliar el espacio, las únicas posibilidades que veo son:

  • dibujar usted mismo, en su propio componente.
  • "piratear" de una forma mediante la adición de una última columna falsa, con un JTableHeader personalizado que no mostraría el último encabezado de columna (y un procesador que evita la cuadrícula para esta última columna). Además, el modo de cambio de tamaño de la tabla debe ser AUTO_RESIZE_LAST_COLUMN, en este caso. Esta es una gran cantidad de condiciones para que funcione, y no estoy seguro de que funcione de todos modos.
+1

El problema con este enfoque es que no agrega un fondo rayado para la parte de la tabla donde no hay celdas. –

+0

@kees - cierto. Normalmente tengo tablas más anchas que el JScrollPane, así que me olvidé de este detalle. Solo noté tu requerimiento en la pregunta, lo siento. Tenga en cuenta que el resaltador de JXTable también funciona solo en las células, ya que también se utiliza en el contexto del "renderizador". Sin embargo, si necesita extenderlo, tendrá que hacerlo usted mismo, ya que la forma en que se representan las tablas se centra únicamente en el área de "celdas" real. – Gnoupi

1

Use Table Row Rendering conceptos que es más fácil que tratar con renderizadores individuales.

Este enfoque solo funciona para celdas renderizadas. Si desea pintar fuera de los límites de la tabla, deberá anular el método paintComponent() para agregar una pintura personalizada.

Cuestiones relacionadas