Java Nimbus每个组件的外观定制(“Nimbus.Overrides”)—其他实例也受到影响
我不熟悉Java Nimbus的外观和感觉。我正在尝试使用Nimbus的功能,使用Java Nimbus每个组件的外观定制(“Nimbus.Overrides”)—其他实例也受到影响,java,swing,look-and-feel,nimbus,Java,Swing,Look And Feel,Nimbus,我不熟悉Java Nimbus的外观和感觉。我正在尝试使用Nimbus的功能,使用putClientProperty(“Nimbus.Overrides”,Overrides)自定义单个组件实例: 我遇到了以下问题(bug?): 不幸的是,“Nimbus.Overrides”值不仅会影响明确设置它的组件对象,还会影响其他对象。 定制属性似乎是以某种方式“继承”到同一类型的其他实例(后来是“样式化”的,显然以前不是)。我需要确保只对一个实例进行更改(不影响任何其他对象)。示例-JButton已使用
putClientProperty(“Nimbus.Overrides”,Overrides)
自定义单个组件实例:
我遇到了以下问题(bug?):
不幸的是,“Nimbus.Overrides”值不仅会影响明确设置它的组件对象,还会影响其他对象。
定制属性似乎是以某种方式“继承”到同一类型的其他实例(后来是“样式化”的,显然以前不是)。我需要确保只对一个实例进行更改(不影响任何其他对象)。示例-JButton
已使用,但与例如JTabbedPane
和自定义画师遇到的问题相同:
-自定义属性A(内容边距)按钮1
-仅自定义属性B(字体)-但属性A中的更改也可见(更大的字体),“以某种方式继承”自按钮2
按钮1
-未自定义属性(使用空属性映射)-这两个更改(A+B)似乎都是从按钮3
和按钮1
继承的(边距越大,字体越大)按钮2
-默认外观为JButton(无自定义)按钮4
我设法找到了一个单行解决方法/黑客。查看我自己对我的问题的答案…如果我更改
UIDefaults
的创建,这对我很有效。而不是
UIDefaults overrides1 = new UIDefaults();
我曾经
UIDefaults overrides1 = (UIDefaults) UIManager.getLookAndFeelDefaults().clone();
对overrides2
和overrides3
也执行此操作:
// 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
这将在我的机器上产生以下输出:
请注意,以这种方式创建的
UIDefaults
的大小可能相当大。我怀疑这是由于javax.swing.plaf.nimbus.NimbusLookAndFeel的shouldUpdatestyleOneEvent
方法中的错误造成的。发件人:
不用说,这不是比较字符串的有效方法。我在bug数据库中找不到任何关于这个的信息;也许等我有时间的时候,我会提交一份bug报告。经过很长时间的调试,似乎我已经找到了一个单行解决方法/hack,这可能也暗示了问题的原因:
if ("UIDefaults".equals(key)) {
compiledDefaults = null;
}
在使用putClientProperty(“Nimbus.Overrides”,Overrides)”设置每个组件的样式后,可以立即使用此代码防止将属性“继承”到随后设置样式的组件:
button1.putClientProperty("Nimbus.Overrides", overrides1);
UIManager.getDefaults().putDefaults(new Object[0]);
// add after each "styling"
// - clears the compiledDefaults in NimbusLookAndFeel
它是干什么的
从功能上讲,没有(empy array=nothing put),但它会触发PropertyChange事件(请参阅源代码),在NimbusLookAndFeel
类(请参阅源代码)的DefaultsListener
私有类中侦听该事件,这是我找到以清除编译默认结果的唯一方法在NimbusLookAndFeel
中,在我看来,这是导致问题的原因:
if ("UIDefaults".equals(key)) {
compiledDefaults = null;
}
在NimbusLookAndFeel
类中的getDefaultsForPrefix
方法(使用compiledDefaults
)的调试过程中,我注意到了这个问题-请参阅源代码对于以后的组件,它不仅返回“真正的默认值”,而且出于某种原因还返回设置到以前组件的自定义属性。
明确地说:我完全是个业余爱好者,对Nimbus课程的细节或架构没有详细的知识或理解。我可能错了,但解决方案对我来说是有效的
不知什么原因,它不合适吗?有风险吗?它真的是一只虫子吗
一个问题:
if ("UIDefaults".equals(key)) {
compiledDefaults = null;
}
我注意到,如果我pack()
myframe不是在使用putClientProperty设置组件样式之前(如我的问题中的代码),而是在之后,则解决方案不起作用(没有任何帮助).这是一个解决方案,但应该没有必要。文档中明确指出,覆盖UIDefaults应该与外观的默认值合并。是的,这个答案可能有效(尚未测试),但它取消了覆盖某些选定属性并将其与默认属性合并的整个过程。将默认属性的整个映射复制到每个单独的组件中一定非常重要…@VGR是的,但这正是不符合预期/记录的工作,请参见我的示例当我编写答案时,我假设Nimbus中存在错误(@VGR感谢深入了解源代码),但我觉得我应该提供一个解决方法。这就是我的答案试图描述的。谢谢你的提示。可能是我做错了,但我尝试在我的NetBeans中调试此方法,并且在我的示例中,在所有情况下,给定字符串的条件都为true(即正确)(尽管比较代码错误),即clearOverridesCache似乎正在运行。似乎问题可能在另一个“缓存”中-看看我自己对我的问题的回答。。。