java AbstractTableModel 2 Different Color For Each Row

前端 未结 3 805
傲寒
傲寒 2020-12-07 00:04

I want to increase readability of my jtable , here is MyTableModel.java class below , how to make each row with 2 different color shown in this picture . What should be t

相关标签:
3条回答
  • 2020-12-07 00:53

    See this Table Row Rendering made by Camick. It'll solve your problem.

    You can use his method createAlternating for rendering the colors of the row.

      private JComponent createAlternating(DefaultTableModel model)
      {
        JTable table = new JTable( model )
        {
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column)
            {
                Component c = super.prepareRenderer(renderer, row, column);
    
                //  Alternate row color
    
                if (!isRowSelected(row))
                    c.setBackground(row % 2 == 0 ? getBackground() : Color.LIGHT_GRAY);
    
                return c;
            }
        };
    
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        table.changeSelection(0, 0, false, false);
        return new JScrollPane( table );
    }
    
    0 讨论(0)
  • 2020-12-07 00:58

    You could...

    Use JXTable from SwingLabs, SwingX library which has functionality which could do this...this would be my preferred solution if you can use 3rd party libraries...

    You could...

    Use Nimbus look and feel which does this...but this precludes you from using other look and feels (like the system look and feel)

    You could...

    Create your own series of custom TableCellRenderers which color their background based on the current row...this is tedious as EVERY cell renderer you might need, needs to be able to perform this operation...

    You could...

    Override the prepareCellRenderer method of the JTable and forcefully set the background of the cell renderer yourself, based on the row...I'm not a fan of this solution, as it's forcing a design choice onto the renderer which might not fit it's requirements (overriding values the cell renderer might want) and locks you into a particular implementation of the table...

    You could...

    Create a JViewport which was capable of talking with the JTable and rendered the candy stripping underneath the table, but the table and renderers would need to be transparent...I've done this, it's...complicated...but allowed me to continue the candy stripping the full length of the view port (beyond the renderable area of the table)...

    Updated with JViewport example

    This is an example of a concept I implemented a while ago for a project (it is actually managed by an interface so I could include JList and JTextArea as well, but that's another question)...

    Basically, it makes the JViewport, which appears below the JTable, responsible for rendering the actual candy stripping.

    But "why?" you ask...because it doesn't affect the table or cell renderer. The only requirement that this makes is that both the table and cell renderers are transparent (unless they have to be otherwise).

    This means, you don't need to put candy stripping logic in your renderers, this means you don't need to override prepareRenderer of every table you create and mangle the requirements of the cell renderers...

    It's far from perfect, but demonstrates the basic idea...

    CandyStripped

    Okay, but why bother? Well, basically, this approach allows you to paint beyond the area painted by the table...

    CandyStripping

    import java.awt.Color;
    import java.awt.Component;
    import java.awt.EventQueue;
    import java.awt.Graphics;
    import java.awt.Graphics2D;
    import java.awt.Rectangle;
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.JViewport;
    import javax.swing.UIManager;
    import javax.swing.UnsupportedLookAndFeelException;
    import javax.swing.table.DefaultTableCellRenderer;
    import javax.swing.table.DefaultTableModel;
    
    public class CandyStrippedTable {
    
        public static void main(String[] args) {
            new CandyStrippedTable();
        }
    
        public CandyStrippedTable() {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    }
    
                    Object[] columns = new Object[10];
                    for (int col = 0; col < columns.length; col++) {
                        columns[col] = (char) (65 + col);
                    }
    
                    Object[][] data = new Object[10][10];
                    for (int row = 0; row < data.length; row++) {
                        for (int col = 0; col < data[row].length; col++) {
                            data[row][col] = row + "x" + col;
                        }
                    }
    
                    DefaultTableModel model = new DefaultTableModel(data, columns);
                    JTable table = new JTable(model);
                    table.setDefaultRenderer(Object.class, new 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);
                            setOpaque(isSelected);
                            return this;
                        }
                        
                    });
                    table.setFillsViewportHeight(true);
                    table.setOpaque(false);
    
                    JScrollPane sp = new JScrollPane();
                    sp.setViewport(new CandyStrippedViewPort(new Color(255, 0, 0, 128)));
                    sp.setViewportView(table);
    
                    JFrame frame = new JFrame("Test");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.add(sp);
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                }
            });
        }
    
        public class CandyStrippedViewPort extends JViewport {
    
            private Color candyStrippedColor;
    
            public CandyStrippedViewPort(Color color) {
                candyStrippedColor = color;
            }
    
            public Color getCandyStrippedColor() {
                return candyStrippedColor;
            }
    
            public void setCandyStrippedColor(Color candyStrippedColor) {
                this.candyStrippedColor = candyStrippedColor;
                repaint();
            }
    
            @Override
            protected void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2d = (Graphics2D) g.create();
                g2d.setColor(getCandyStrippedColor());
                Component view = getView();
                if (view instanceof JTable) {
                    JTable table = (JTable) view;
                    Rectangle viewRect = getViewRect();
                    int y = 0;
                    int row = 0;
                    if (table.getRowCount() > 0) {
                        row = table.rowAtPoint(viewRect.getLocation());
                        while (row < table.getRowCount()) {
                            int rowHeight = table.getRowHeight(row);
                            Rectangle cellRect = table.getCellRect(row, 0, true);
                            if (row % 2 == 0) {
                                g2d.fillRect(0, cellRect.y - viewRect.y, getWidth(), cellRect.height);
                            }
                            y = cellRect.y + cellRect.height;
                            row++;
                        }
                    }
                    int rowHeight = table.getRowHeight();
                    while (y < getHeight()) {
                        if (row % 2 == 0) {
                            g2d.fillRect(0, y, getWidth(), rowHeight);
                        }
                        row++;
                        y += rowHeight;
                    }
                }
                g2d.dispose();
            }
        }
    }
    

    Formatting numbers in cell renderers

    You could start with something like...

    obj.table.setDefaultRenderer(Double.class, 
        new DefaultTableCellRenderer() { 
            @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 
                if (value instanceof Number) {
                    value = NumberFormat.getNumberInstance().format(value);
                }
                super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 
                setOpaque(isSelected); 
                return this; 
            } 
        });
    

    If, for some reason, the default format instead suitable, you could do something like...

    obj.table.setDefaultRenderer(Double.class, 
        new DefaultTableCellRenderer() { 
            @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 
                if (value instanceof Number) {
                    NumberFormat ni = NumberFormat.getNumberInstance();
                    ni.setMaximumFractionDigits(2)
                    value = ni.format(value);
                }
                super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 
                setOpaque(isSelected); 
                return this; 
            } 
        });
    

    Instead

    0 讨论(0)
  • 2020-12-07 00:58

    long time ago, i had the same problem.

    In this case i use the JXTable from the swingX library instead of the JTable. This componenet has a great method:

    addHighlighter(HighlighterFactory.createSimpleStriping());
    

    good luck

    0 讨论(0)
提交回复
热议问题