Java Nimbus LAF与透明文本字段

时间:2009-03-05 04:48:45

标签: java swing nimbus

我有一个应用程序在几个透明的地方使用禁用的JTextFields - 允许显示背景而不是文本字段的正常背景。

当运行新的Nimbus LAF时,这些字段是不透明的(尽管设置了setOpaque(false)),并且我的UI被破坏了。好像LAF忽略了不透明的属性。明确地设置背景颜色在几个地方都很难,并且由于背景图像实际上不起作用而不是最佳 - 它仍然在顶部绘制LAF默认背景,留下类似边框的外观(下面的启动画面明确设置背景以匹配图像。)

关于如何让Nimbus不为JTextField绘制背景的任何想法?

注意:我需要一个JTextField而不是JLabel,因为我需要线程安全的setText()和包装功能。

注意:我的后备位置是继续使用系统LAF,但Nimbus确实看起来好多了。

见下面的示例图片。


结论

此行为的意外是由于误解了setOpaque()的意图 - 来自Nimbus错误报告:

  

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); }

Example

alt text

4 个答案:

答案 0 :(得分:17)

上周我使用JTextPane遇到了同样的问题。当使用除nimbus之外的任何外观时,setOpaque()方法按预期工作。显然,nimbus的外观和感觉改变了我们对许多组件的setOpaque()所期望的行为。根据您的看法,它可以被视为一个错误。查看关于这个sun bugid的评论:

nimbus opaque 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),就像我一样。

答案 1 :(得分:0)

嘿,有软件猴子。

mmhh如何安装实际遵守setOpaque行为的UI的子类替换。

我认为它类似于setUI或类似的东西。

你可以抓住灵气的源代码,看看那里有什么东西(如果它在那里),将它子类化并安装“固定”的。

你的声音很有趣,你有我们能看到的截图吗?

答案 2 :(得分:0)

我认为问题是如何解释“不透明”和“背景”。 对于JTextfield,有一个问题:“哪些可见部分是背景?”。我将“背景”定义为边界矩形的部分,它们不是由组件绘制的。 对于“圆形”按钮,例如,这将是圆形外的角。 因此我会说JTextfield没有可见的背景!它有一个矩形的形状,你所采取的背景不是场的背景,而是场的画布。


从OP反驳

这是一个有趣的想法,值得回答未来观众的答案(而不是评论)。

我不同意。我认为边界外部分的部分不是组件的一部分 - 它是外部组件。具有圆角的区域必然是非不透明的,因为它不能负责绘制它的整个矩形区域 - 这是所有组件的尺寸为矩形的副作用。

我认为这种考虑使得isOpaque()的现有(和被误解的)含义成为争论。它也使我的论点不应该存在setOpaque(),并且setBackground(null)应该导致组件不绘制背景。

我会提出,文本字段的背景确实是其边界内区域的颜色,我认为你不会发现很多人会对此作出直观的结论 - 因此背景适用于该区域遵守API用户的最小惊喜规则。

答案 3 :(得分:0)

来自javadoc

  

public void setBackground(Color bg)

     

设置此组件的背景颜色。背景颜色是   仅在组件不透明时使用   并且只能通过JComponent的子类   或ComponentUI实现。直接   JComponent的子类必须覆盖   paintComponent来尊重这个属性。

     

尊重这个属性取决于外观和感觉,有些人可能会选择   忽略它。