Java Nimbus Look and Feel per component customization ("Nimbus.Overrides") - 其他实例也受影响

标签 java swing look-and-feel nimbus

我是 Java Nimbus 外观和感觉 的新手。我正在尝试使用 Nimbus 的功能来自定义单个组件实例,使用 putClientProperty("Nimbus.Overrides", overrides) : https://docs.oracle.com/javase/8/docs/api/javax/swing/plaf/nimbus/package-summary.html

我遇到了以下问题(错误?):

不幸的是,“Nimbus.Overrides”值显然不仅会影响其明确设置的组件对象,还会影响其他对象。

似乎自定义属性以某种方式“继承”到相同类型的其他(后来“样式化”,显然不是以前)实例。我需要确保只对一个单独的实例进行更改(不影响任何其他对象)。示例 - JButton使用过,但遇到了与例如相同的问题JTabbedPane和定制画家:

  • button 1 - 自定义属性 A(内容边距)。
  • button 2 - 仅属性 B(字体)自定义 - 但属性 A 的更改也可见(更大的 manrgins),“以某种方式继承”自 button 1 .
  • button 3 - 没有自定义属性(使用空属性映射) - 两个更改 (A+B) 似乎都是从 button1 继承的(更大的边距,更大的字体)和 button2
  • button 4 - 默认外观 o JButton(无自定义)

    import java.awt.FlowLayout;
    import java.awt.Font;
    import java.awt.Insets;
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.UIDefaults;
    
    
    public class NimbusPerComponentTest extends JFrame {
    
    public NimbusPerComponentTest()  {
        super("Test");
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setLayout(new FlowLayout());
    
        // 4 buttons to test
        JButton button1 = new JButton("Button 1");
        JButton button2 = new JButton("Button 2");
        JButton button3 = new JButton("Button 3");
        JButton button4 = new JButton("Button 4");
        add(button1);
        add(button2);
        add(button3);
        add(button4);
        pack();
    
        // style        
        // button 1
        UIDefaults overrides1 = new UIDefaults();
        overrides1.put("Button.contentMargins", new Insets(10,10,10,10));        
        button1.putClientProperty("Nimbus.Overrides", overrides1);
        // button 2
        UIDefaults overrides2 = new UIDefaults();        
        overrides2.put("Button.font", new Font("Sans Serif", Font.BOLD, 15));
        button2.putClientProperty("Nimbus.Overrides", overrides2);
        // button 3
        UIDefaults overrides3 = new UIDefaults();
            // nothing = left empty
        button3.putClientProperty("Nimbus.Overrides", overrides3);
        // button 4
        // no styling        
    
    }
    
    public static void main(String args[]) {        
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(NimbusPerComponentTest.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }       
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                new NimbusPerComponentTest().setVisible(true);
            }
        });
    }
    }            
    

enter image description here

知道为什么吗?我错过了什么?任何优雅的解决方法? (Java 8, Windows 10)

编辑

经过一些答案的启发:

尝试在我的原始代码末尾重置外观(为 null 并再次返回到 Nimbus,包括 SwingUtilities.updateComponentTreeUI),唯一的结果是:

现在即使是 button4 也画错了(边距和字体都改变了),尽管通用默认值从未被触及......很奇怪。

编辑 2

我设法找到了一个单行解决方法/hack。查看我自己对我的问题的回答...

最佳答案

如果我更改 UIDefaults 的创建,它对我有用。而不是

UIDefaults overrides1 = new UIDefaults();

我用过

UIDefaults overrides1 = (UIDefaults) UIManager.getLookAndFeelDefaults().clone();

overrides2overrides3 也执行此操作:

    // style
    // button 1
    UIDefaults overrides1 = (UIDefaults) UIManager.getLookAndFeelDefaults().clone();
    overrides1.put("Button.contentMargins", new Insets(10, 10, 10, 10));
    button1.putClientProperty("Nimbus.Overrides", overrides1);
    // button 2
    UIDefaults overrides2 = (UIDefaults) UIManager.getLookAndFeelDefaults().clone();
    overrides2.put("Button.font", new Font("Sans Serif", Font.BOLD, 15));
    button2.putClientProperty("Nimbus.Overrides", overrides2);
    // button 3
    UIDefaults overrides3 = (UIDefaults) UIManager.getLookAndFeelDefaults().clone();
    // nothing = left empty
    button3.putClientProperty("Nimbus.Overrides", overrides3);
    // button 4
    // no styling

这会在我的机器上产生以下输出:

Screenshot with my modifications

请注意,以这种方式创建的 UIDefaults 的大小可能非常大。

关于Java Nimbus Look and Feel per component customization ("Nimbus.Overrides") - 其他实例也受影响,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49815702/

相关文章:

JavaFX 线程卡住

java - 使用ArrayList登录系统

java - 使用 Java Swing 高效重画线条

Java Swing : dispose() a JFrame does not clear its controls

java - 如何在 Java Swing 中使用 double 值设置 JTextpane 中文本的字体大小

java - Quaqua 外观问题

java - Eclipse IDE 能够生成 javacard cap 文件,但在命令行中我遇到此错误

java - PLAF 无法更改按钮颜色

Java GTK+ 原生外观和感觉看起来很糟糕且大胆

java - 使用自定义排序功能实现 Treeset