Java Nimbus-覆盖表格标题的颜色

Java Nimbus-覆盖表格标题的颜色,java,swing,colors,nimbus,jtableheader,Java,Swing,Colors,Nimbus,Jtableheader,我想在使用Nimbus L&F时覆盖JTables中标题的背景色。我正在有效地“主题化”Nimbus L&F,即对其进行小的调整 无论我尝试什么,似乎都没有效果 这是一个: 结果如下: 我很清楚Nimbus是Synth L&F,所以它几乎可以用s来做任何事情。我打赌我可以覆盖UIManager中的一些Painter,但我不想从头开始重做Painter。Nimbus的画家非常先进,他们使用渐变和你有的东西。我想利用这一点。这正是我想改变的颜色。这里有一个可能的解决方案,但相当难看 Nimbus严

我想在使用Nimbus L&F时覆盖
JTable
s中标题的背景色。我正在有效地“主题化”Nimbus L&F,即对其进行小的调整

无论我尝试什么,似乎都没有效果

这是一个:

结果如下:


我很清楚Nimbus是Synth L&F,所以它几乎可以用s来做任何事情。我打赌我可以覆盖
UIManager
中的一些
Painter
,但我不想从头开始重做Painter。Nimbus的画家非常先进,他们使用渐变和你有的东西。我想利用这一点。这正是我想改变的颜色。

这里有一个可能的解决方案,但相当难看

Nimbus严重依赖于
Painter
s。Nimbus看起来不错的原因是它使用了渐变、阴影等等。这是
画家的工作。我们真的,真的不想做我们自己的画家。灵光画家非常复杂,并产生了美丽的效果。所以我们想利用它们。不要自己动手

Nimbus有很多自动生成的源代码。所有源代码都是从
skin.laf
XML文件(位于JDK源代码中)生成的,但在运行时不使用XML文件。大多数自动生成的源文件实际上是特定于类型的
Painter
s。例如,有一个painter类用于
tableheaderrenderpainter
(负责绘制表格标题的painter)等等。问题是所有自动生成的源代码都是包私有的

在初始化NimbusLookAndFeel实例时设置绘制者。在这之后他们不会改变

skin.laf
文件中,我们可以看到什么颜色用于什么。在我们的例子中,我们可以看到实际上是
nimbusBlueGrey
颜色控制了表标题的背景色。我们不能只更改
nimbusBlueGrey
的值,因为这会影响Nimbus中使用此颜色的所有内容。所以我们需要想出别的办法。这就是它变得丑陋的地方

在特定情况下,我们对默认情况下的表格标题感兴趣(即当鼠标不在其上方时,表格未被禁用,列标题未被按下,等等)。这就是我们将在下面集中讨论的内容。但是这种技术对于其他任何类型的特殊装饰都是一样的

这项技术是首先启动
NimbusLookAndFeel
的临时实例。我们这样做只是为了“偷走”它产生的一位画家。我们不希望安全地保存这个画师,然后启动
NimbusLookAndFeel
进行真正的绘制。现在,我们可以替换我们的特定画师,以便替换先前保存的画师

public class MyTest {

    public static void main(String[] args) throws UnsupportedLookAndFeelException {
        new MyTest();
    }

    public MyTest() throws UnsupportedLookAndFeelException {

        // Start dummy instance of L&F
        NimbusLookAndFeel nimbusTmp = new NimbusLookAndFeel();
        Object nimbusBlueGreyOrg = UIManager.get("nimbusBlueGrey");  // original value
        UIManager.put("nimbusBlueGrey", Color.RED);   // the color we want
        try {
            UIManager.setLookAndFeel(nimbusTmp);
        } catch (UnsupportedLookAndFeelException ex) {
            Logger.getLogger(MyTest.class.getName()).log(Level.SEVERE, null, ex);
        }
        Object painter = UIManager.get("TableHeader:\"TableHeader.renderer\"[Enabled].backgroundPainter");

        // We've got what we came for. Now unload the dummy.
        UIManager.getLookAndFeel().uninitialize(); // important to avoid UIDefaults change listeners firing
        UIManager.put("nimbusBlueGrey", nimbusBlueGreyOrg);  // revert

        // Load the L&F for real. 
        UIManager.setLookAndFeel(new NimbusLookAndFeel());

        // Swap in the value we saved previously
        UIManager.put("TableHeader:\"TableHeader.renderer\"[Enabled].backgroundPainter", painter);

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            DefaultTableModel model = new DefaultTableModel(
                    new Object[][]{
                        {"hhvt ", "er sdf", "sfdg"},
                        {"hyshg ", "dh sdf", "jer"}},
                    new Object[]{"Col A", "Col B", "Col C"}
            );
            JTable table = new JTable(model);    
            setLayout(new BorderLayout());
            add(new JScrollPane(table));
        }

    }

}

我并不为此感到骄傲,但它确实有效。有人有更好的想法吗?

我想这里有几次,包括关于的详细描述,提示--->仍然是关于XxxRenderer的,而不是关于UIManager中的键(为什么要费心处理不可访问的键,或者设置不费吹灰之力就没有任何效果)对于Nimbus L&F,最好使用为金属L指定的标准渲染器/荧光灯概念&F@mKorbel. 恐怕我不理解你的任何评论。无论如何,有一个更新:从源代码看,Nimbus中的表头背景似乎是硬编码的,以选择以下颜色:
nimbusBorder
nimbusBlueGrey
nimbusFocus
nimbusBase
。然后,它会从中创建渐变。不同的州有不同的颜色,等等。但这些是总共使用的颜色。一切都是从这些衍生出来的。问题是,我不想更改它们本身,我只想影响表标题。
我只想影响表标题。
提示-->仍然是关于XxxRenderer
您是说,如果不设置特定的渲染器,这是无法做到的吗,
您是说如果不设置特定的渲染器,则无法执行此操作,而不是使用1。标准的TableCellRenderer(然后您可以覆盖所有键和鼠标事件并正确地执行),2。一些基于Nimbus的L&F解决了访问所有密钥的问题(包括JTabbedPane:-),感谢分享。我也在为此挣扎。太棒了!这个解决方案是我发现的最有趣的,手动更改整个LAF会更难看p与此相比,该解决方案非常优雅。
public class MyTest {

    public static void main(String[] args) throws UnsupportedLookAndFeelException {
        new MyTest();
    }

    public MyTest() throws UnsupportedLookAndFeelException {

        // Start dummy instance of L&F
        NimbusLookAndFeel nimbusTmp = new NimbusLookAndFeel();
        Object nimbusBlueGreyOrg = UIManager.get("nimbusBlueGrey");  // original value
        UIManager.put("nimbusBlueGrey", Color.RED);   // the color we want
        try {
            UIManager.setLookAndFeel(nimbusTmp);
        } catch (UnsupportedLookAndFeelException ex) {
            Logger.getLogger(MyTest.class.getName()).log(Level.SEVERE, null, ex);
        }
        Object painter = UIManager.get("TableHeader:\"TableHeader.renderer\"[Enabled].backgroundPainter");

        // We've got what we came for. Now unload the dummy.
        UIManager.getLookAndFeel().uninitialize(); // important to avoid UIDefaults change listeners firing
        UIManager.put("nimbusBlueGrey", nimbusBlueGreyOrg);  // revert

        // Load the L&F for real. 
        UIManager.setLookAndFeel(new NimbusLookAndFeel());

        // Swap in the value we saved previously
        UIManager.put("TableHeader:\"TableHeader.renderer\"[Enabled].backgroundPainter", painter);

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            DefaultTableModel model = new DefaultTableModel(
                    new Object[][]{
                        {"hhvt ", "er sdf", "sfdg"},
                        {"hyshg ", "dh sdf", "jer"}},
                    new Object[]{"Col A", "Col B", "Col C"}
            );
            JTable table = new JTable(model);    
            setLayout(new BorderLayout());
            add(new JScrollPane(table));
        }

    }

}