Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JTable row hightlighter based on value from TableCell

Tags:

java

swing

jtable

as I read that not possible to Encode my Navajo language

finging the way how to only alternate/striped Color into JTable (example @camickr)

enter image description here

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableRowRenderingTip extends JPanel {

    private static final long serialVersionUID = 1L;

    public TableRowRenderingTip() {
        Object[] columnNames = {"Type", "Company", "Shares", "Price", "Boolean"};
        Object[][] data = {
            {"Buy", "IBM", new Integer(1000), new Double(80.5), Boolean.TRUE},
            {"Sell", "Dell", new Integer(2000), new Double(6.25), Boolean.FALSE},
            {"Short Sell", "Apple", new Integer(3000), new Double(7.35), Boolean.TRUE},
            {"Buy", "MicroSoft", new Integer(4000), new Double(27.50), Boolean.FALSE},
            {"Short Sell", "Cisco", new Integer(5000), new Double(20), Boolean.TRUE}
        };
        DefaultTableModel model = new DefaultTableModel(data, columnNames) {

            private static final long serialVersionUID = 1L;

            @Override
            public Class getColumnClass(int column) {
                return getValueAt(0, column).getClass();
            }
        };
        JTabbedPane tabbedPane = new JTabbedPane();
        tabbedPane.addTab("Alternating", createAlternating(model));
        add(tabbedPane);
    }

    private JComponent createAlternating(DefaultTableModel model) {
        JTable table = new JTable(model) {

            private static final long serialVersionUID = 1L;

            @Override
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                Component c = super.prepareRenderer(renderer, row, column);
                if (!isRowSelected(row)) { //  Alternate row color
                    c.setBackground(row % 2 == 0 ? getBackground() : Color.LIGHT_GRAY);
                }
                return c;
            }
        };
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        return new JScrollPane(table);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                createAndShowGUI();
            }
        });
    }

    public static void createAndShowGUI() {
        JFrame.setDefaultLookAndFeelDecorated(false);
        JFrame frame = new JFrame("Table Row Rendering");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new TableRowRenderingTip());
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

I have a JTable which contains some market trades (better for understanding by reason my poor English skills), but some of deals has only one leg, but another (for example vanilla Cross Currency Swap) could have two legs. How is possible to hightlighting TableRows based on value from specifics TableColumn (for example last column with name DealId). I tried to check row with row - 1 && row + 1, but my empty head generated lots of codesRow, to much for idea how to stop complicated simple simple things, how to check if there exist duplicate value in another row (always with strict ordering as captured in the pictures). No idea how to implements simple formula for that

pictures demonstrated:

enter image description here
enter image description hereenter image description here

generated from code:

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class TablePrepareRenderer extends JFrame {

    private static final long serialVersionUID = 1L;
    private Object[] columnNames = {
        "Buy/Sell", "Type", "SubType", "Ccy1", "Amount1", "Ccy2", "Amount2", "DealId"};
    private Object[][] data = {
        {"Buy&Sell", "Ccy Swap", "A1", "EUR", new Double(1000000.00), "USD", new Double(1439000.00), 50},
        {"Buy&Sell", "Ccy Swap", "A3", "USD", new Double(1438900.00), "EUR", new Double(1000000.00), 50},
        {"Buy&Sell", "Ccy Swap", "A1", "EUR", new Double(500000.00), "CHF", new Double(550000.00), 350},
        {"Buy&Sell", "Ccy Swap", "A1", "CHF", new Double(549800.00), "EUR", new Double(500000.00), 350},
        {"Sell&Buy", "Ccy Swap", "A3", "USD", new Double(1000000.00), "EUR", new Double(749000.00), 2250},
        {"Sell&Buy", "Ccy Swap", "A1", "EUR", new Double(748900.00), "USD", new Double(1000000.00), 2250},
        {"Buy&Sell", "Ccy Swap", "A1", "GBP", new Double(1000000.00), "USD", new Double(1638100.00), 400},
        {"Buy&Sell", "Ccy Swap", "A3", "USD", new Double(1638200.00), "GBP", new Double(1000000.00), 400},
        {"Sell", "Ccy Spot", "A1", "AUD", new Double(343575.0), "EUR", new Double(250000.0), 11990},
        {"Buy", "Ccy Spot", "A1", "EUR", new Double(100000.00), "JPY", new Double(1099000.00), 259},
        {"Sell", "Ccy Fwd", "A3", "DKK", new Double(74889.00), "EUR", new Double(10000.00), 115439},};
    private JTable table;

    public TablePrepareRenderer() {

        DefaultTableModel model = new DefaultTableModel(data, columnNames);

        table = new JTable(model) {

            private static final long serialVersionUID = 1L;

            @Override
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                Component c = super.prepareRenderer(renderer, row, column);
                JComponent jc = (JComponent) c;
                /*if (!isRowSelected(row)) {
                c.setBackground(getBackground());
                int modelRow = convertRowIndexToModel(row);
                String type = (String) getModel().getValueAt(modelRow, 0);
                if (("Buy".equals(type)) && !("Buy&Sell".equals(type))) {
                c.setBackground(Color.orange);
                } else if (("Sell".equals(type)) && !("Sell&Buy".equals(type))) {
                c.setBackground(Color.orange);
                } else if ("Buy&Sell".equals(type)) {
                c.setBackground(Color.yellow);
                } else if ("Sell&Buy".equals(type)) {
                c.setBackground(Color.yellow);
                }
                }*/
                /*if (!isRowSelected(row)) {
                if (row == 0 ||row == 1||row == 4||row == 6||row == 7||row == 9||row == 10) {
                ((JComponent) c).setBackground(Color.orange);
                }  else {
                ((JComponent) c).setBackground(Color.yellow);
                }
                }*/

                if (!isRowSelected(row)) {
                    if (row == 0 || row == 1 || row == 4 || row == 5 || row == 8 || row == 10) {
                        ((JComponent) c).setBackground(Color.orange);
                    } else {
                        ((JComponent) c).setBackground(Color.yellow);
                    }
                }

                if (column == 0 || column == 1 || column == 2 || column == 3 || column == 5) {
                    //setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
                    //c.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
                    //(JComponent) c.setHorizontalAlignment(javax.swing.SwingConstants.CENTER);
                }
                return c;
            }

            @Override
            public Class getColumnClass(int column) {
                switch (column) {
                    case 0:
                        return String.class;
                    case 1:
                        return String.class;
                    case 2:
                        return String.class;
                    case 3:
                        return String.class;
                    case 4:
                        return Double.class;
                    case 5:
                        return String.class;
                    case 6:
                        return Double.class;
                    case 7:
                        return Integer.class;
                }
                return null;
            }
        };
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane(table);
        getContentPane().add(scrollPane);
    }

    public static void main(String[] args) {
        TablePrepareRenderer frame = new TablePrepareRenderer();
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

Edit:

how to set Alignment for TableCell into prepareRenderer,

like image 771
mKorbel Avatar asked Aug 20 '11 14:08

mKorbel


2 Answers

how to set Alignment for TableCell into prepareRenderer,

This should NOT be done in the prepareRenderer code. This property should be set in the renderer for the class or for the column because it only applies to a specific class or renderer. Instead use:

table.setPreferredScrollableViewportSize(table.getPreferredSize());
DefaultTableCellRenderer stringRenderer = (DefaultTableCellRenderer)table.getDefaultRenderer(String.class);
stringRenderer.setHorizontalAlignment( SwingConstants.CENTER );

For the highlighting code I used code that assumes that the dealld value is unique for a given set of transactions:

        private Map<Object, Color> rowColor = new HashMap<Object, Color>();
        private Color nextColor = Color.ORANGE;

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

            if (isRowSelected(row)) return c;

            Object value = table.getValueAt(row, 7);
            Color background = rowColor.get(value);

            if (background != null)
            {
                c.setBackground( background );
            }
            else
            {
                rowColor.put(value, nextColor);
                c.setBackground( nextColor );
                nextColor = (nextColor == Color.ORANGE) ? Color.YELLOW : Color.ORANGE;
            }

            return c;
        }

Note: It won't work if sorting is required.

Here is another approach that should work even if sorting is required (but I didn't test it with sorting);

        @Override
        public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
            Component c = super.prepareRenderer(renderer, row, column);
            JComponent jc = (JComponent) c;
            if (!isRowSelected(row))
            {
                c.setBackground(getRowBackground(row));
            }

            return c;
        }

        private Color getRowBackground(int row)
        {
            boolean isDark = true;

            Object previous = getValueAt(0, 7);

            for (int i = 1; i <= row; i++)
            {
                Object current = getValueAt(i, 7);

                if (! current.equals(previous))
                {
                    isDark = !isDark;
                    previous = current;
                }
            }

            return isDark ? Color.ORANGE : Color.YELLOW;
        }
like image 123
camickr Avatar answered Oct 19 '22 15:10

camickr


it's Sunday, wheather detoriating, so couldn't resist to show the SwingX version. It's the same logic as @camickr 2nd, thanks :-)

Advantages:

  • code can focus on logic as the value retrieving handles sorting/filtering/column moves automagically
  • knows about default ui alternate striping colors (and updates on switching the LAF)
  • Highlighter support is built-in, no need to subclass the table nor care about renderer misbehaviour
  • easy to add additional highlighters (yelling sell, sell, sell :-)

The code snipped:

JXTable table = new JXTable(data, columnNames);
HighlightPredicate predicate =  new HighlightPredicate() {

    @Override
    public boolean isHighlighted(Component renderer,
            ComponentAdapter adapter) {
        if (adapter.row == 0) return false;
        return isOddValue(adapter);
    }

    private boolean isOddValue(ComponentAdapter adapter) {
        Object previous = adapter.getFilteredValueAt(0, 7);
        boolean odd = false;
        for (int i = 1; i <= adapter.row; i++) {
            Object current = adapter.getFilteredValueAt(i, 7);
            if (!previous.equals(current)) {
                odd = !odd;
            }
            previous = current;
        }
        return odd;
    }

};
table.addHighlighter(new UIColorHighlighter(predicate));
like image 30
kleopatra Avatar answered Oct 19 '22 15:10

kleopatra