JTable with striped background

前端 未结 5 1338
北恋
北恋 2021-02-06 06:14

Using a different background color for odd and even rows is a commonly used trick to improve readability of large tables.

I want to use this effect in Swing\'s JTable.

相关标签:
5条回答
  • 2021-02-06 06:21

    Either use JXTable or if you are super-lazy ( or super time-short :-)) ) you can just use "Nimbus" look-and-feel, JTable looks there stripped by default :)

    0 讨论(0)
  • 2021-02-06 06:23

    The JXtable provided by swingx allow you to implements such rendering Take a look at http://swinglabs.org/docs/components/JXTable/tutorial.jsp?step=3#RowHighlighting

    0 讨论(0)
  • 2021-02-06 06:29

    You can also use a custom TableCellRenderer which will pick the color for you, with a part of code like this inside:

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

    Edit: I missed the fact that you tried that already, and that you need to extend this color to the space without cells. To my knowledge, this is not possible with the current implementation of JTable or JXTable. The highlighters from JXTable are mostly sophisticated renderers, they still cater only to cells.

    To extend the space, the only possibilities I see are:

    • draw it yourself, in your own component.
    • "hack" a way by adding a fake last column, with a custom JTableHeader which wouldn't display the last column header (and a renderer avoiding the grid for this last column). Also, the table resizing mode should be AUTO_RESIZE_LAST_COLUMN, in this case. This is a lot of conditions to make it work, and I'm not really sure it would work anyway.
    0 讨论(0)
  • 2021-02-06 06:41

    Use Table Row Rendering concepts which is easier than dealing with individual renderers.

    This approach only works for rendered cells. If you want to paint outside the bounds of the table, then you will need to override the paintComponent() method to add custom painting.

    0 讨论(0)
  • 2021-02-06 06:46

    Use getCellRect( getRowCount() - 1, 0, true ).y to get the top y-coordinate of the empty space, and then paint some Rectangles and (Grid-)Lines with paintComponent( Graphics g ).

    jtable with empty space grid

    To make it much easier for you, here's a long (but complete) solution ;-)

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

    This example could be extended to:

    • fix the painted pseudogrid for variable RowHeights (I'm using the lowest height used in any row)
    • explain to the user why nothing happens if he clicks in the empty space to edit the cells (via tooltip)
    • add an extra row to the table model if the user clicks in the empty space (nooo! no Excel please!)
    • use the empty space to draw a reflection of the table (including all rendered data ( what for? ;-) )
    0 讨论(0)
提交回复
热议问题