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用户的最小惊喜规则。