Swing JTable,自定义标题渲染器和排序图标

Swing JTable,自定义标题渲染器和排序图标,swing,header,jtable,renderer,Swing,Header,Jtable,Renderer,在JTable标题上设置自定义渲染器时,我获得了预期的视觉行为(边框、字体、对齐方式等),但我无法获得行排序时通常出现的LaF排序图标 以下是设置自定义标题渲染器的代码: Enumeration<TableColumn> columns = getColumnModel().getColumns(); while (columns.hasMoreElements()) columns.nextElement().setHeaderRenderer(new XDeliver

在JTable标题上设置自定义渲染器时,我获得了预期的视觉行为(边框、字体、对齐方式等),但我无法获得行排序时通常出现的LaF排序图标

以下是设置自定义标题渲染器的代码:

Enumeration<TableColumn> columns = getColumnModel().getColumns();
   while (columns.hasMoreElements())
   columns.nextElement().setHeaderRenderer(new XDeliveryTableHeaderRenderer());
public class MyTableHeaderRenderer extends JLabel implements TableCellRenderer {
     private static final Font labelFont = new Font("Arial", Font.BOLD, 11);

     @Override
     public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        setFont(labelFont);
        setHorizontalAlignment(SwingConstants.CENTER);
        setText(value.toString());
        setBorder(BorderFactory.createEtchedBorder());
        return this;
     }
}
public class MyTableHeaderRenderer implements TableCellRenderer {
 private static final Font labelFont = new Font("Arial", Font.BOLD, 11);

 private TableCellRenderer delegate;

 public MyTableHeaderRenderer(TableCellRenderer delegate) {
     this.delegate = delegate;
 } 

 @Override
 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

    Component c = delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

    if(c instanceof JLabel) {
        JLabel label = (JLabel) c;
        label.setFont(labelFont);
        label.setHorizontalAlignment(SwingConstants.CENTER);
        label.setBorder(BorderFactory.createEtchedBorder());
    }
    return c;
 }
}

// Usage:
JTableHeader header = table.getTableHeader();
header.setDefaultRenderer(new MyTableHeaderRenderer(header.getDefaultRenderer()));

有任何提示吗?

请尝试委派给L&F安装的渲染器:

Enumeration<TableColumn> columns = getColumnModel().getColumns();
   while (columns.hasMoreElements())
   columns.nextElement().setHeaderRenderer(new XDeliveryTableHeaderRenderer());
public class MyTableHeaderRenderer extends JLabel implements TableCellRenderer {
     private static final Font labelFont = new Font("Arial", Font.BOLD, 11);

     @Override
     public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
        setFont(labelFont);
        setHorizontalAlignment(SwingConstants.CENTER);
        setText(value.toString());
        setBorder(BorderFactory.createEtchedBorder());
        return this;
     }
}
public class MyTableHeaderRenderer implements TableCellRenderer {
 private static final Font labelFont = new Font("Arial", Font.BOLD, 11);

 private TableCellRenderer delegate;

 public MyTableHeaderRenderer(TableCellRenderer delegate) {
     this.delegate = delegate;
 } 

 @Override
 public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {

    Component c = delegate.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

    if(c instanceof JLabel) {
        JLabel label = (JLabel) c;
        label.setFont(labelFont);
        label.setHorizontalAlignment(SwingConstants.CENTER);
        label.setBorder(BorderFactory.createEtchedBorder());
    }
    return c;
 }
}

// Usage:
JTableHeader header = table.getTableHeader();
header.setDefaultRenderer(new MyTableHeaderRenderer(header.getDefaultRenderer()));

正如克利奥帕特拉所警告的,这可能不是最稳定的解决方案,看看我刚刚在生产中得到的。该问题的报告者建议使用一个自定义的Table/TableColumn子类来更新TableColumn#getDefaultRenderer中的委托呈现器。

不幸的是,这没有起到作用。扩展JLabel并实现TableCellRenderer会产生一个具有相同背景颜色且没有边框的标题(因此需要显式设置边框)。您建议的解决方案(通过…setHeaderRenderer(new MyTableHeaderRenderer(new DefaultTableCellRenderer())调用)创建了一个具有白色背景且仍然没有排序图标的标题,但排序机制仍在工作。啊,抱歉,忘记了,您需要传递table.getTableHeader()而不是传递new DefaultTableCellRenderer().getDefaultRenderer()。经过适当的注意、尝试、测试和赞赏。它工作起来很有魅力,谢谢:)基本上就是这样,只是一个小小的注意:头渲染器高度依赖LAF,它们的实现差别很大。因此,a)该简单设置将无法在LAF的生命周期内保持不变,b)期望特定类型的渲染器的LAF可能决定不正确配置组件c)排序图标可能位于任何位置,即边界中或占据标签图标。因此,期待前面的问题:-)至于第三个警告,我检查了它,同时玩弄带有自己图标的自定义标题渲染器,如
if(label.getIcon()==null)label.setIcon(MY_STOCK_ICONS[columnIndex])。我认为拥有两个自定义标题图标+LAF排序图标需要手动合并这两个资源,但这(目前)超出了我的应用程序的范围。谢谢你,克莱奥。