Java Nimbus LAF与透明文本字段
我有一个应用程序在几个地方使用禁用的JTextFields是透明的 – 允许显示背景而不是文本字段的正常背景。
运行新的Nimbus LAF时,这些字段是不透明的(尽管设置了setOpaque(false)),并且我的UI被破坏了。 好像LAF忽略了不透明的属性。 明确地设置背景颜色在几个地方都很困难,并且由于背景图像实际上不起作用而不是最佳 – 它仍然在顶部绘制LAF默认背景,留下类似边框的外观(下面的启动画面具有明确设置为匹配图像的背景)。
关于如何让Nimbus不为JTextField绘制背景的任何想法?
注意:我需要一个JTextField而不是JLabel,因为我需要线程安全的setText()和包装function。
注意:我的后备位置是继续使用系统LAF,但Nimbus确实看起来好多了。
见下面的示例图片。
结论
这种行为的惊喜是由于对Nimbus错误报告中setOpaque()的意图的错误解释:
这是Swing的原始设计以及它多年来一直令人困惑的问题。 问题是setOpaque(false)在退出LAF时产生了副作用,即隐藏背景并不是真正的背景。 可以说,我有透明部分和swing的组件应该在其后面绘制父组件。
不幸的是,Nimbus组件似乎也不尊重setBackground(null),否则这将是停止背景绘制的推荐方法。 设置完全透明的背景对我来说似乎不直观。
在我看来,setOpaque()/ isOpaque()是一个错误的公共API选择,应该只有:
public boolean isFullyOpaque();
我这样说,因为isOpaque()== true是与Swing的契约,组件子类将负责绘制它的整个背景 – 这意味着父级可以跳过绘制该区域(如果它需要)(这是一个重要的性能增强)。 外部的东西不能直接改变这个合同(合法地),其履行可以编码到组件中。
因此,不应使用setOpaque()设置组件的不透明度。 相反,像setBackground(null)之类的东西会导致许多组件“没有背景”,因此变得不完全不透明。 举例来说,在理想的世界中,大多数组件应该具有如下所示的isOpaque():
public boolean isOpaque() { return (background!=null); }
示例http://sofzh.miximages.com/java/sviczq.png
替代文字http://sofzh.miximages.com/java/35d80ao.png
我上周使用JTextPane遇到了同样的问题。 当使用除nimbus之外的任何外观时,setOpaque()方法按预期工作。 显然,nimbus的外观和感觉改变了我们对许多组件的setOpaque()所期望的行为。 根据您的看法,它可以被视为一个错误。 检查这个sun bugid的评论:
雨云不透明的bug
对我有用的解决方法是:
myPane.setOpaque(false); // added by OP myPane.setBorder(BorderFactory.createEmptyBorder()); myPane.setBackground(new Color(0,0,0,0));
来自OP的注意事项:我还必须确保JTextField的setOpaque(false)以便绘制父背景 – 只是想为其他人提及这一点,以防他们尝试使用setOpaque(true),就像我一样。
嘿有软件猴子。
mmhh如何安装UI的子类替换实际上尊重setOpaque行为。
我认为它类似于setUI或类似的东西。
你可以抓住灵气的源代码,看看那里有什么东西(如果它在那里),将它子类化并安装“固定”的。
你的声音很有趣,你有我们可以看到的截图吗?
来自javadoc
public void setBackground(Color bg)
设置此组件的背景颜色。 仅当组件不透明时才使用背景颜色,并且仅使用JComponent或ComponentUI实现的子类。 JComponent的直接子类必须覆盖paintComponent才能使用此属性。
尊重这个属性取决于外观和感觉,有些人可能会选择忽略它。
我认为问题是如何解释“不透明”和“背景”。 对于JTextfield,有一个问题:“背景是什么可见部分?”。 我将“背景”定义为边界矩形的部分,它们不是由组件绘制的。 对于“圆形”按钮,例如,这将是圆圈外的角落。 因此我会说JTextfield没有可见的背景! 它有一个矩形的形状,你所采取的背景不是场的背景,而是场的canvas。
来自OP的反驳
这是一个有趣的想法,值得回答未来观众的答案(而不是在评论中)。
我不同意。 我认为边界外部分的部分不是组件的一部分 – 它在组件之外 。 具有圆角的区域必然是非不透明的,因为它不能负责绘制它的整个矩形区域 – 这是所有组件在尺寸上是矩形的副作用。
我认为这种考虑使得isOpaque()的现有(和被误解的)含义的论证。 它也使我的论点setOpaque()不应该存在,并且setBackground(null)应该导致组件不绘制背景。
我会提出,文本字段的背景确实是其边界内区域的颜色,我认为你不会发现很多人会对此作出直观的结论 – 因此有背景适用于该地区的服从API用户的最小惊喜规则。