这可以通过实现自定义TableCellRenderer 来完成。特别是通过将默认标题渲染器包装在自定义TableCellRenderer 中并在检测到对该列进行排序时使用所需的前景色修改它来重用默认标题渲染器(因为排序图标、颜色和标签)将很有用:
import java.awt.Color;
import java.awt.Component;
import java.util.List;
import java.util.Objects;
import javax.swing.DefaultRowSorter;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.RowSorter.SortKey;
import javax.swing.SortOrder;
import javax.swing.SwingUtilities;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
public class SortedRowHeaderRendererDemo {
private static class SortedRowHeaderRenderer implements TableCellRenderer {
private final TableCellRenderer originalRenderer;
private Color originalForeground;
public SortedRowHeaderRenderer(final TableCellRenderer originalRenderer) {
this.originalRenderer = Objects.requireNonNull(originalRenderer);
originalForeground = null;
}
@Override
public Component getTableCellRendererComponent(final JTable table,
final Object value,
final boolean isSelected,
final boolean hasFocus,
final int row,
final int column) {
final Component original = originalRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (row < 0 && original instanceof JComponent) {
final JComponent originalJComponent = (JComponent) original;
if (originalForeground == null)
originalForeground = originalJComponent.getForeground();
Color fg = originalForeground;
final RowSorter<?> sorter = table.getRowSorter();
if (sorter instanceof DefaultRowSorter) {
final List<? extends SortKey> keys = sorter.getSortKeys();
if (!keys.isEmpty()) {
final SortKey k = keys.get(0); /*The first key is the most
significant one for sorting, ie the last selected sorting column.*/
if (k.getColumn() == table.convertColumnIndexToModel(column)) {
final SortOrder order = k.getSortOrder();
if (SortOrder.ASCENDING.equals(order))
fg = Color.RED;
else if (SortOrder.DESCENDING.equals(order))
fg = Color.GREEN;
//Don't forget here that there are also 'SortOrder.UNSORTED' and 'null' values for 'order'!
}
}
}
originalJComponent.setForeground(fg);
}
return original;
}
}
private static void createAndShowGUI() {
final String addedOnColumn = "Added on";
final JTable table = new JTable(new Object[][] {
new Object[]{"Data001", "Data002", "Data003"},
new Object[]{"Data011", "Data012", "Data013"},
new Object[]{"Data021", "Data022", "Data023"},
new Object[]{"Data031", "Data032", "Data033"},
new Object[]{"Data041", "Data042", "Data043"}
}, new Object[] {"Column1", "Column2", addedOnColumn});
table.setAutoCreateRowSorter(true);
final TableColumn col = table.getColumn(addedOnColumn);
col.setHeaderRenderer(new SortedRowHeaderRenderer(table.getTableHeader().getDefaultRenderer()));
final JFrame frame = new JFrame("Table renderer demo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(new JScrollPane(table));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(SortedRowHeaderRendererDemo::createAndShowGUI);
}
}
特征:
一个特性(或者更确切地说是错误修复)是该代码也适用于启用了列重新排序的表。
限制:
- 包装后的
TableCellRenderer 必须返回JComponent 才能设置其前景属性,该属性应该是文本的颜色。例如支持返回JLabels 的TableCellRenderers(如DefaultTableCellRenderers)。但是,如果使用预安装或默认渲染器,情况似乎就是这样。
- 表的
RowSorter 必须是DefaultRowSorter 类型(例如TableRowSorter),以便确定列是否已排序以及它的排序顺序。那是因为RowSorter 类没有做出任何保证,因为我检查了它的getSortKeys 方法返回的SortKeys 的顺序。另一方面,DefaultRowSorter 保证“排序是根据当前的 SortKeys 完成的,为了" (我假设 SortKeys 由 getSortKeys 方法返回的顺序在这里隐含)。默认情况下,JTable 虽然似乎已经创建了一个 DefaultRowSorter。