我不熟悉Java Nimbus的外观和感觉。我正在尝试使用Nimbus的功能,使用putClientProperty(“Nimbus.Overrides”,Overrides)
定制单个组件实例:https://docs.oracle.com/javase/8/docs/api/javax/swing/plaf/nimbus/package-summary.html
我遇到了以下问题(bug?):
不幸的是,“Nimbus.Overrides”值显然不仅会影响它被明确设置的组件对象,还会影响其他对象。
定制属性似乎是以某种方式“继承”到同一类型的其他实例(后来是“样式化的”,显然以前不是)。我需要确保只对一个实例进行更改(不影响任何其他对象)。示例-JButton
已使用,但与例如JTabbedPane
和自定义画师遇到的问题相同:
>
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);
}
});
}
}
知道为什么吗?我错过了什么?有什么优雅的变通方法吗?(Java8,视窗10)
编辑
经过一些答案的启发:
尝试在我的原始代码末尾重置lookandfeel(设置为null并再次返回Nimbus,包括SwingUtilities.updateComponentTreeUI),唯一的结果是:
现在甚至连按钮4都画错了(边距和字体都变了),尽管通用默认值从未被触及...奇怪。
编辑2
我设法找到了一条单行线的解决方法。看看我自己对我的问题的回答。。。
我怀疑这是由于javax的shouldUpdateStyleOneEvent
方法中的一个错误造成的。摆动普拉夫。光轮。NimbusLookAndFeel。来源:
protected boolean shouldUpdateStyleOnEvent(PropertyChangeEvent ev) {
String eName = ev.getPropertyName();
// These properties affect style cached inside NimbusDefaults (6860433)
if ("name" == eName ||
"ancestor" == eName ||
"Nimbus.Overrides" == eName ||
"Nimbus.Overrides.InheritDefaults" == eName ||
"JComponent.sizeVariant" == eName) {
JComponent c = (JComponent) ev.getSource();
defaults.clearOverridesCache(c);
return true;
}
return super.shouldUpdateStyleOnEvent(ev);
}
不用说,这不是比较字符串的有效方法。我在bug数据库中找不到任何与此相关的信息;也许等我有时间的时候,我会提交一份bug报告。
经过相当长时间的调试,我似乎已经找到了一个单行的解决方法/破解方法,这可能也表明了问题的原因:
使用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
私有类中监听该事件,这是我设法找到的清除compiledDefaults
缓存(?)在NimbusLookAndFeel
中,在我看来,这是导致问题的原因:
if ("UIDefaults".equals(key)) {
compiledDefaults = null;
}
我注意到在NimbusLookAnd感到
类中的getDefaultsForPrefix
方法(使用compiledDefault
)调试期间存在问题-请参阅此处的源代码。对于更高版本的组件,它不仅返回“真正的默认值”,而且由于某种原因还返回设置为前一个组件的自定义属性。
明确地说:我完全是个业余爱好者,对Nimbus课程的细节或架构没有详细的知识或理解。我可能错了,但解决方案对我来说是有效的。。。
它是否因某种原因不适合?有风险吗?它真的是一个错误吗?
一个问题:
我注意到,如果在使用putClientProperty设置组件的样式之前(就像我在问题中的代码中那样),但在之后,我pack()
my frame,那么解决方案就不起作用了(没有任何帮助)。。。
如果我更改UIDefault
的创建,它对我有用。而不是
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
的大小可能相当大。
我有n个服务器线程,每个线程都听1个客户端。 当一个服务器线程从其客户端接收到消息时,它需要通知其他“n-1”客户端,这就是为什么我在服务器线程之间保留一个共享对象(包含一个“n”套接字数组,每个客户端一个)。 此外,在持有的主服务器线程中,每次我接受与客户端的新连接时,我都会打开一个,使用从返回的新套接字向他给出第一个答案。 在回答“OK”的情况下,我打开一个新线程,将新套接字传递给它,以便监听
我试图通过名为LoginController的控制器获取客户端IP,但错误仍然存在。 传递给App\Http\Controller\Auth\LoginController的参数1::a的验证()必须是App\Http\Controller\Auth\Request的实例,给定Illumate\Http\Request的实例 我已经跟随这个SO问题,但仍然得到相同的错误。 所以,我刚刚发现了Aut
问题内容: 我负责四种不同的Jenkins安装-两台测试服务器和两台生产服务器。 在Jenkins中,我有哪些选择可以使我更清楚地知道连接到哪台计算机? 我想做的是能够将屏幕顶部的Jenkins文本更改为“ Jenkins Department 1 Test”-这可能吗?还有其他选项,例如更改颜色等吗? 问题答案: 我认为最简单的方法是使用“ 简单主题插件”。 Jenkins的插件,支持自定义CS
DocBook 输出为 Html 时,如果不使用 CSS 控制,那么它的外观将比较“朴素” 如果自己写一个 CSS 未免太麻烦,可以随便找一个 DocBook 写的文档,将里面的 CSS 文件拿来修改[58] 通过例子简单介绍下 CSS body { font-family: verdana, tahoma, helvetica, arial, sans-serif; text-alig
我使用的是ListView,每个列表元素上都有几个按钮。 单击行上的按钮时,该按钮应消失。单击按钮时,单击的按钮会消失,这没关系。问题是其他一些列表元素按钮也不见了。 例如,当我点击第一元素按钮时,它也会影响第六、第十一、第十六元素中的按钮。 原因是适配器没有为数据中的所有元素创建列表元素。它只创建了几个足以在屏幕上显示的对象。如图所示,在列表中向下移动时,top元素成为最后一个元素,其值也发生了
JavaScript对象Module控制了运行时相关的很多行为。在之前的章节中,我们尝试了: 使用Module.onRuntimeInitialized回调在运行时准备就绪后执行测试代码。 通过更改Module.TOTAL_MEMORY设置内存容量。 我们可以使用类似的方法更改Module的标准输出行为,例如: <!--custom_print.html--> <script> Module