Java JTable行标题外观和感觉

Java JTable行标题外观和感觉,java,swing,jtable,look-and-feel,jtableheader,Java,Swing,Jtable,Look And Feel,Jtableheader,我正在尝试为我的JTable创建行标题。我已经做了研究,但几乎什么都没有。我的发现并没有保持系统的外观 到目前为止,我发现: 第一列(没有名字的那列)是我能做到的最好的。我使用了表头渲染器并将其应用于行单元格。这在一定程度上起了作用。正如您所看到的,降序/升序排序的小箭头图标出现在列的每个单元格中,该单元格现在为灰色。除此之外,这是一次彻底的失败。此外,我不希望我的行标题中有任何箭头图标 Col 1是我尝试应用UIManager的外观时发生的情况。显然,它没有起作用 Col 2是photosh

我正在尝试为我的JTable创建行标题。我已经做了研究,但几乎什么都没有。我的发现并没有保持系统的外观

到目前为止,我发现:

第一列(没有名字的那列)是我能做到的最好的。我使用了表头渲染器并将其应用于行单元格。这在一定程度上起了作用。正如您所看到的,降序/升序排序的小箭头图标出现在列的每个单元格中,该单元格现在为灰色。除此之外,这是一次彻底的失败。此外,我不希望我的行标题中有任何箭头图标

Col 1是我尝试应用UIManager的外观时发生的情况。显然,它没有起作用

Col 2是photoshop,这正是我想要做的

我没有对其他2列做任何操作,因此它是默认设置

问题是: 如何将系统(不仅仅是windows)默认表头的外观赋予行单元格,以便创建行头,当然还有一个小箭头图标

这是代码

import java.awt.Component;
import java.awt.Dimension;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;
import sun.swing.table.DefaultTableCellHeaderRenderer;

public class RowHeaderTest extends JFrame
{

    public RowHeaderTest()
    {
        initComponents();
    }

    private void initComponents()
    {
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

        JScrollPane scrollPane = new JScrollPane();
        JTable table = new JTable();
        table.setAutoCreateRowSorter(true);
        table.getTableHeader().setReorderingAllowed(false);
        table.setModel(new DefaultTableModel(
                new Object[][]
                {
                    {
                        "Row 1", "Data 2", "Data 3", "Data 4", "Data 5"
                    },
                    {
                        "Row 2", "Data 6", "Data 7", "Data 8", "Data 9"
                    },
                    {
                        "Row 3", "Data 10", "Data 11", "Data 12", "Data 13"
                    }
                },
                new String[]
                {
                    "", "Col 1", "Col 2", "Col 3", "Col 4"
                }));
        table.getColumnModel().getColumn(0).setHeaderRenderer(HeaderRenderer.THIS);
        table.getColumnModel().getColumn(0).setCellRenderer(HeaderRenderer.THIS);
        table.getColumnModel().getColumn(1).setHeaderRenderer(HeaderRendererUI.THIS);
        table.getColumnModel().getColumn(1).setCellRenderer(HeaderRendererUI.THIS);
        table.getColumnModel().getColumn(3).setHeaderRenderer(RowTableHeaderRendere.THIS);
        table.getColumnModel().getColumn(3).setCellRenderer(RowTableHeaderRendere.THIS);
        scrollPane.setViewportView(table);
        setSize(new Dimension(400, 200));
        setLocationRelativeTo(null);
        add(scrollPane);
    }

    public static void main(String args[])
    {
        try
        {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        }
        catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex)
        {
            java.util.logging.Logger.getLogger(RowHeaderTest.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        java.awt.EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                new RowHeaderTest().setVisible(true);
            }
        });
    }
}

final class HeaderRenderer extends DefaultTableCellHeaderRenderer
{

    public static final HeaderRenderer THIS = new HeaderRenderer();

    @Override
    public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column)
    {
        TableCellRenderer renderer = table.getTableHeader().getDefaultRenderer();
        return renderer.getTableCellRendererComponent(table, value, isSelected,
                hasFocus, row, column);
    }
}

final class HeaderRendererUI extends DefaultTableCellHeaderRenderer
{

    public static final HeaderRendererUI THIS = new HeaderRendererUI();

    @Override
    public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column)
    {
        setText(value.toString());
        //TableHeader.ancestorInputMap
        setBackground(isSelected ? UIManager.getColor("TableHeader.focusCellBackground") : UIManager.getColor("TableHeader.background"));
        setBorder(UIManager.getBorder("TableHeader.cellBorder"));
        setFont(UIManager.getFont("TableHeader.font"));
        setForeground(UIManager.getColor("TableHeader.foreground"));
        return this;
    }
}

final class RowTableHeaderRendere extends DefaultTableCellHeaderRenderer
{

    public static final RowTableHeaderRendere THIS = new RowTableHeaderRendere();

    @Override
    public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected,
            boolean hasFocus, int row, int column)
    {
        JTable t = new JTable(new DefaultTableModel(
                null,
                new String[]
                {
                    value.toString()
                }));
        return t.getTableHeader();
    }
}
编辑


我只是在代码中添加了部分解决方案。Col 3现在外观不错,但仍然缺乏感觉(它没有鼠标悬停),我不确定创建一个新表来获取标题是否是最好的方法。

要保持系统的外观和感觉,需要稍微更改渲染器

首先,使用uiresource扩展渲染器。您需要此标记接口来接收UI更改:

class HeaderRenderer extends DefaultTableCellHeaderRenderer 
                     implements javax.swing.plaf.UIResource {
然后从JTableHeader中获取并保留原始渲染器(例如,作为构造函数传递的字段defRenderer)。在GetTableCellRenderComponent中,调用defRenderer.GetTableCellRenderComponent,修改并返回此JLabel

private final TableCellRenderer defRenderer;

HeaderRenderer (TableCellRenderer defRenderer) {
  this.defRenderer = defRenderer;
}

@Override
public Component getTableCellRendererComponent(
        JTable table, Object value, boolean isSelected,
        boolean hasFocus, int row, int column) {
  Component c = defRenderer.getTableCellRendererComponent (...);
  if ( c instanceof JLabel ) {
    JLabel lbl = (JLabel)c;
    // do anything you want...
  }
  return c;
}
至少覆盖渲染器中的updateUI()方法,并删除对defRenderer的updateUI调用:

@Override
public void updateUI() {
  TableCellRenderer locDefRenderer = defRenderer;
  if (locDefRenderer instanceof JComponent) {
    ((JComponent) locDefRenderer).updateUI();
  } else {
    super.updateUI();
  }
}

有了这张收据,可以改变很多事情。素描组件渲染稍微复杂一点;-)-对于自己的绘画,请使用JLayer(在Java 7中介绍)

欢迎来到“我讨厌你的外观和感觉”的精彩世界。
DefaultTableCellHeaderRenderer
的实现不是基于
TableHeader
默认使用的实现begin。这里有一些尝试,包括好的,非常好的,2。问题什么是真正的目标3。Rorrorter ets可能存在问题。(未经审判)4+1用于发布漂亮的问题,带有图片和SSCCE,5。很容易回答-->不要在渲染器中设置任何内容,渲染器是装饰器而不是属性或值生成器6。与L&F无关,但由于从渲染器重复调用UIManager的键(一堆事件放在那里System.out.println),在另一个L&Fs中也存在同样的问题。基本上,您无法获得标题中的确切视觉效果:lafs配置渲染器时偏向于将其用作columnHeader。要去掉排序图标,请输入一个空表。一个肮脏的技巧(在此上下文中没有尝试)是使用图像:让laf相信它正在将渲染器配置为columnHeader,然后将该图像绘制到单元格渲染器中。是否有一种方法可以创建单个标题并简单返回它有渲染组件?好的,我刚刚创建了一个空表并从中获取标题。现在我有了好看的外观,但仍然缺乏感觉。我将把代码作为部分答案发布。