do not recreate the Icon
inside the Renderer
, prepare it earlier, otherwise you recreate the Icon
in crazy periods
do not add Icon
to Component / JComponent / JLabel
returns Renderer
enter Renderer
code created by Darryl or Rob
protected Icon getIcon(JTable table, int column) { SortKey sortKey = getSortKey(table, column); if (sortKey != null && table.convertColumnIndexToView( sortKey.getColumn()) == column) { switch (sortKey.getSortOrder()) { case ASCENDING: return UIManager.getIcon("Table.ascendingSortIcon"); case DESCENDING: return UIManager.getIcon("Table.descendingSortIcon"); } } return null; }
EDIT
thanks Renderer @trashgod , UNSORTED no need to redefine for Renderer, try and enjoy
initial view
Ascend
DESCENDING
Unsorted
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 ImageChangeDemo extends JFrame { private static final long serialVersionUID = 1L; private JTable table = new javax.swing.JTable(); public static void main(String args[]) { //comment out the code below to try in Metal L&F try { for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { javax.swing.UIManager.setLookAndFeel(info.getClassName()); break; } } } catch (Exception ex) { ex.printStackTrace(); } java.awt.EventQueue.invokeLater(new Runnable() { @Override public void run() { new ImageChangeDemo().setVisible(true); } }); } public ImageChangeDemo() { setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); JScrollPane pane = new javax.swing.JScrollPane(); 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) { setSortKeys(null); return; } } } super.toggleSortOrder(column); } }; table.setRowSorter(sorter); table.setPreferredScrollableViewportSize(table.getPreferredSize()); table.setDefaultRenderer(ImageChangeDemo.class, new HeaderRenderer(table)); pane.setViewportView(table); add(pane); pack(); } 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; } } }
EDIT 2
then set the icon directly in UIManager
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.RowSorter.SortKey; import javax.swing.SortOrder; import javax.swing.UIManager; import javax.swing.table.TableModel; import javax.swing.table.TableRowSorter; public class ImageChangeDemo extends JFrame { private static final long serialVersionUID = 1L; private JTable table = new javax.swing.JTable(); public static void main(String args[]) { //comment out the code below to try in Metal L&F try { for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) { if ("Nimbus".equals(info.getName())) { javax.swing.UIManager.setLookAndFeel(info.getClassName()); UIManager.getLookAndFeelDefaults().put("Table.ascendingSortIcon", new BevelArrowIcon(BevelArrowIcon.UP, false, false)); UIManager.getLookAndFeelDefaults().put("Table.descendingSortIcon", new BevelArrowIcon(BevelArrowIcon.DOWN, false, false)); break; } } } catch (Exception ex) { ex.printStackTrace(); } java.awt.EventQueue.invokeLater(new Runnable() { @Override public void run() { new ImageChangeDemo().setVisible(true); } }); } public ImageChangeDemo() { setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); JScrollPane pane = new javax.swing.JScrollPane(); //table.setAutoCreateRowSorter(true); 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) { setSortKeys(null); return; } } } super.toggleSortOrder(column); } }; table.setRowSorter(sorter); //table.getTableHeader().setDefaultRenderer(new DefaultTableHeaderCellRenderer()); //table.setDefaultRenderer(ImageChangeDemo.class, new HeaderRenderer(table)); table.setPreferredScrollableViewportSize(table.getPreferredSize()); pane.setViewportView(table); add(pane); pack(); } 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); } } }