RowSorter not set in renderer

746 views Asked by At

I implement icon for sorting column in my jTable. I have a button for find result and i implement a default sorting when i launch the worker. Like this :

public void refreshStripedViewTable(final List<FlightBox> boxList,
        final List<FlightBoxModel> boxesModels, final String sortBy) {
        if (boxList != null && !boxList.isEmpty()) {
            stripedViewTableModel.setContent(boxesModels);
            tableRenderer.setStripedViewModelList(boxesModels);
            final RowSorter<? extends TableModel> sorter = tableFacade
                .getTooltipsTable().getRowSorter();
            if (sorter != null) {
                List<SortKey> sortKeys = new ArrayList<SortKey>();
                javax.swing.RowSorter.SortKey sk = new SortKey(getColumnIndex(
                    sortBy, tableFacade.getTooltipsTable()),
                    SortOrder.ASCENDING);
                sortKeys.add(sk);
                sorter.setSortKeys(sortKeys);
                tableFacade.getTooltipsTable().setRowSorter(sorter);
                tableFacade.getTooltipsTable().validate();
                tableFacade.getTooltipsTable().getModelTable()
                    .fireTableDataChanged();
            }
        }
    }

i add a renderer for setIcon when user click on header on my JTable.

public Component getTableCellRendererComponent(final JTable table,
        final Object value, final boolean isSelected, final boolean hasFocus,
        final int row, final int column) {
        setIcon(null);
        super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
            row, column);
        setOpaque(false);
        setForeground(Color.white);
        final RowSorter<?> sorter = table.getRowSorter();
        if (sorter != null) {
            java.util.List<? extends javax.swing.RowSorter.SortKey> sortKeys = sorter
                .getSortKeys();
            if (sortKeys.size() > 0) {
                javax.swing.RowSorter.SortKey sk = sortKeys.get(0);
                // take in account if the user moves the column
                if (column == table.convertColumnIndexToView(sk.getColumn())) {
                    Icon icon = null;
                    if (sk.getSortOrder() == SortOrder.ASCENDING) {
                        icon = iconService
                            .getRessourceIcon(MediaHmiService.TABLE_SORT_ORDER_ASCENDING);
                    } else if (sk.getSortOrder() == SortOrder.DESCENDING) {
                        icon = iconService
                            .getRessourceIcon(MediaHmiService.TABLE_SORT_ORDER_DESCENDING);
                    }
                    setIcon(icon);
                }
            }
        }
        setHorizontalTextPosition(SwingConstants.LEFT);
        return this;
    }

I have a problem when i do this : - Found result --> Icon is set on default column sorting OK - Click on header for set icon OK - Relaunch search --> Not icon is visible.KO My renderer don't have sortKeys but i set rowSorter in my methode refreshStripedViewTable().I don't understand why...

Thanks guys for your help. Regards.

2

There are 2 answers

0
mKorbel On
  • note there are three types of SortOrder

  • ASCENDING

enter image description here

  • DESCENDING

enter image description here

  • UNSORTED

enter image description here

f.i.

import java.awt.Component;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.UIManager;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class RowSorterDefaults {

    private static final long serialVersionUID = 1L;
    private JFrame frame = new JFrame();
    private JScrollPane pane = new javax.swing.JScrollPane();
    private JTable table = new javax.swing.JTable();

    public RowSorterDefaults() {
        table.setModel(new javax.swing.table.DefaultTableModel(
                new Object[][]{
                    {"a", "q", "h", "v"}, {"b", "m", "l", "h"},
                    {"d", "c", "a", "d"}, {"j", "o", "y", "e"}
                },
                new String[]{
                    "Col 1", "Col 2", "Col 3", "Col 4"
                }) {
            private static final long serialVersionUID = 1L;
            Class[] types = new Class[]{
                String.class, String.class, String.class, String.class
            };

            @Override
            public Class getColumnClass(int columnIndex) {
                return types[columnIndex];
            }
        });
        TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel()) {
            @Override
            public void toggleSortOrder(int column) {
                if (column >= 0 && column < getModelWrapper().getColumnCount() && isSortable(column)) {
                    List<SortKey> keys = new ArrayList<SortKey>(getSortKeys());
                    if (!keys.isEmpty()) {
                        SortKey sortKey = keys.get(0);
                        if (sortKey.getColumn()
                                == column && sortKey.getSortOrder()
                                == SortOrder.DESCENDING) {//UNSORTED, ASCENDING
                            setSortKeys(null);
                            return;
                        }
                    }
                }
                super.toggleSortOrder(column);
            }
        };
        table.setRowSorter(sorter);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        table.setDefaultRenderer(RowSorterDefaults.class, new HeaderRenderer(table));
        pane.setViewportView(table);
        frame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        frame.add(pane);
        frame.pack();
        frame.setVisible(true);
    }

    class HeaderRenderer implements TableCellRenderer {

        final TableCellRenderer renderer;

        public HeaderRenderer(JTable table) {
            renderer = table.getTableHeader().getDefaultRenderer();
        }

        @Override
        public Component getTableCellRendererComponent(
                JTable table, Object value, boolean isSelected,
                boolean hasFocus, int row, int col) {
            return renderer.getTableCellRendererComponent(
                    table, value, isSelected, hasFocus, row, col);
        }

        public Icon getIcon(JTable table, int column) {
            for (RowSorter.SortKey sortKey : table.getRowSorter().getSortKeys()) {
                if (sortKey.getColumn() == column) {
                    switch (sortKey.getSortOrder()) {
                        case ASCENDING:
                            return (UIManager.getIcon("Table.ascendingSortIcon"));
                        case DESCENDING:
                            return (UIManager.getIcon("Table.descendingSortIcon"));
                    }
                }
            }
            return null;
        }
    }

    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new RowSorterDefaults();
            }
        });
    }
}
0
mKorbel On

I have a problem when i do this : - Found result --> Icon is set on default column sorting OK - Click on header for set icon OK - Relaunch search --> Not icon is visible.KO My renderer don't have sortKeys but i set rowSorter in my methode refreshStripedViewTable().I don't understand why...

Icon are added as defaults to UIManager, then all JTables in current JVM has the same Icons

  • ASCENDING

enter image description here

  • DESCENDING

enter image description here

  • UNSORTED

enter image description here

f.i.

import java.awt.Color;
import java.awt.Component;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SortOrder;
import javax.swing.UIManager;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class RowSorterCustom {

    private static final long serialVersionUID = 1L;
    private JFrame frame = new JFrame();
    private JScrollPane pane = new javax.swing.JScrollPane();
    private JTable table = new javax.swing.JTable();

    public RowSorterCustom() {
        table.setModel(new javax.swing.table.DefaultTableModel(
                new Object[][]{
                    {"a", "q", "h", "v"}, {"b", "m", "l", "h"},
                    {"d", "c", "a", "d"}, {"j", "o", "y", "e"}
                },
                new String[]{
                    "Col 1", "Col 2", "Col 3", "Col 4"
                }) {
            private static final long serialVersionUID = 1L;
            Class[] types = new Class[]{
                String.class, String.class, String.class, String.class
            };

            @Override
            public Class getColumnClass(int columnIndex) {
                return types[columnIndex];
            }
        });
        TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel()) {
            @Override
            public void toggleSortOrder(int column) {
                if (column >= 0 && column < getModelWrapper().getColumnCount() && isSortable(column)) {
                    List<SortKey> keys = new ArrayList<SortKey>(getSortKeys());
                    if (!keys.isEmpty()) {
                        SortKey sortKey = keys.get(0);
                        if (sortKey.getColumn()
                                == column && sortKey.getSortOrder()
                                == SortOrder.DESCENDING) {//UNSORTED, ASCENDING
                            setSortKeys(null);
                            return;
                        }
                    }
                }
                super.toggleSortOrder(column);
            }
        };
        table.setRowSorter(sorter);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        pane.setViewportView(table);
        frame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        frame.add(pane);
        frame.pack();
        frame.setVisible(true);
    }

    static class BevelArrowIcon implements Icon {

        public static final int UP = 0;         // direction
        public static final int DOWN = 1;
        private static final int DEFAULT_SIZE = 11;
        private Color edge1;
        private Color edge2;
        private Color fill;
        private int size;
        private int direction;

        public BevelArrowIcon(int direction, boolean isRaisedView, boolean isPressedView) {
            if (isRaisedView) {
                if (isPressedView) {
                    init(UIManager.getColor("controlLtHighlight"),
                            UIManager.getColor("controlDkShadow"),
                            UIManager.getColor("controlShadow"),
                            DEFAULT_SIZE, direction);
                } else {
                    init(UIManager.getColor("controlHighlight"),
                            UIManager.getColor("controlShadow"),
                            UIManager.getColor("control"),
                            DEFAULT_SIZE, direction);
                }
            } else {
                if (isPressedView) {
                    init(UIManager.getColor("controlDkShadow"),
                            UIManager.getColor("controlLtHighlight"),
                            UIManager.getColor("controlShadow"),
                            DEFAULT_SIZE, direction);
                } else {
                    init(UIManager.getColor("controlShadow"),
                            UIManager.getColor("controlHighlight"),
                            UIManager.getColor("control"),
                            DEFAULT_SIZE, direction);
                }
            }
        }

        public BevelArrowIcon(Color edge1, Color edge2, Color fill, int size, int direction) {
            init(edge1, edge2, fill, size, direction);
        }

        @Override
        public void paintIcon(Component c, Graphics g, int x, int y) {
            switch (direction) {
                case DOWN:
                    drawDownArrow(g, x, y);
                    break;
                case UP:
                    drawUpArrow(g, x, y);
                    break;
            }
        }

        @Override
        public int getIconWidth() {
            return size;
        }

        @Override
        public int getIconHeight() {
            return size;
        }

        private void init(Color edge1, Color edge2, Color fill, int size, int direction) {
            edge1 = Color.red;
            edge2 = Color.blue;
            this.edge1 = edge1;
            this.edge2 = edge2;
            this.fill = fill;
            this.size = size;
            this.direction = direction;
        }

        private void drawDownArrow(Graphics g, int xo, int yo) {
            g.setColor(edge1);
            g.drawLine(xo, yo, xo + size - 1, yo);
            g.drawLine(xo, yo + 1, xo + size - 3, yo + 1);
            g.setColor(edge2);
            g.drawLine(xo + size - 2, yo + 1, xo + size - 1, yo + 1);
            int x = xo + 1;
            int y = yo + 2;
            int dx = size - 6;
            while (y + 1 < yo + size) {
                g.setColor(edge1);
                g.drawLine(x, y, x + 1, y);
                g.drawLine(x, y + 1, x + 1, y + 1);
                if (0 < dx) {
                    g.setColor(fill);
                    g.drawLine(x + 2, y, x + 1 + dx, y);
                    g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
                }
                g.setColor(edge2);
                g.drawLine(x + dx + 2, y, x + dx + 3, y);
                g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
                x += 1;
                y += 2;
                dx -= 2;
            }
            g.setColor(edge1);
            g.drawLine(xo + (size / 2), yo + size - 1, xo + (size / 2), yo + size - 1);
        }

        private void drawUpArrow(Graphics g, int xo, int yo) {
            g.setColor(edge1);
            int x = xo + (size / 2);
            g.drawLine(x, yo, x, yo);
            x--;
            int y = yo + 1;
            int dx = 0;
            while (y + 3 < yo + size) {
                g.setColor(edge1);
                g.drawLine(x, y, x + 1, y);
                g.drawLine(x, y + 1, x + 1, y + 1);
                if (0 < dx) {
                    g.setColor(fill);
                    g.drawLine(x + 2, y, x + 1 + dx, y);
                    g.drawLine(x + 2, y + 1, x + 1 + dx, y + 1);
                }
                g.setColor(edge2);
                g.drawLine(x + dx + 2, y, x + dx + 3, y);
                g.drawLine(x + dx + 2, y + 1, x + dx + 3, y + 1);
                x -= 1;
                y += 2;
                dx += 2;
            }
            g.setColor(edge1);
            g.drawLine(xo, yo + size - 3, xo + 1, yo + size - 3);
            g.setColor(edge2);
            g.drawLine(xo + 2, yo + size - 2, xo + size - 1, yo + size - 2);
            g.drawLine(xo, yo + size - 1, xo + size, yo + size - 1);
        }
    }

    public static void main(String args[]) {
        UIManager.getLookAndFeelDefaults().put("Table.ascendingSortIcon", new BevelArrowIcon(BevelArrowIcon.UP, false, false));
        UIManager.getLookAndFeelDefaults().put("Table.descendingSortIcon", new BevelArrowIcon(BevelArrowIcon.DOWN, false, false));
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new RowSorterCustom();
            }
        });
    }
}