【问题标题】:Java Nimbus LAF with transparent text fields具有透明文本字段的 Java Nimbus LAF
【发布时间】:2010-10-11 10:43:03
【问题描述】:

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

在运行新的 Nimbus LAF 时,这些字段是不透明的(尽管设置了 setOpaque(false)),并且我的 UI 已损坏。就好像 LAF 忽略了 opaque 属性。 明确地设置背景颜色在几个地方都很困难,并且由于背景图像而不是最佳的实际上不起作用 - 它仍然在顶部绘制它的 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); }

【问题讨论】:

  • 你已经浏览过这个包了吗? src.zip!\com\sun\java\swing\plaf\nimbus

标签: java swing nimbus


【解决方案1】:

嘿,软件猴子。

mmhh 安装真正尊重 setOpaque 行为的 UI 的子类替换怎么样。

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

您可以获取 nimbus 的源代码,看看那里出了什么问题(如果有的话),将其子类化并安装“已修复”的代码。

你的听起来很有趣,你有截图我们可以看到吗?

【讨论】:

  • 如果唯一的选择是这个,我想我会坚持使用系统 LAF。至少那时我在 Linux、OSX 和其他平台上运行时不太可能有惊喜。
【解决方案2】:

上周我在使用 JTextPane 时遇到了同样的问题。当使用 nimbus 以外的任何外观和感觉时,setOpaque() 方法会按预期工作。显然,nimbus 的外观和感觉改变了我们对许多组件使用 setOpaque() 所期望的行为。根据你如何看待它,它可以被认为是一个错误。检查这个太阳虫上的 cmets:

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)。

【讨论】:

  • 这看起来很有希望;今晚将在我的应用程序中尝试。谢谢。
  • @juggler555:谢谢,只要组件不透明(当我让它不透明时,文本更新“潦草”在前一个顶部)。
【解决方案3】:

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


OP的反驳

这是一个足够有趣的想法,值得在未来观众的答案中做出回应(而不是在 cmets 中)。

我不得不不同意。我会争辩说,边框外的组件部分不是组件的一部分 - 它是 outside 组件。具有圆角的字段必然是不透明的,因为它不能负责绘制整个矩形区域 - 这是所有组件在尺寸上都是矩形的副作用。

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

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

【讨论】:

  • 上面提到的错误似乎讲述了同样的故事。
  • @ordnungswidrig:你的答案很难解读,但我很犹豫要不要编辑它,并冒着把话塞进你嘴里的风险——你想再看一遍吗?
  • @Ordnungswidrig:有趣的想法 - 我对你的回答添加了反驳,因为我认为这是一个重要的想法。
【解决方案4】:

来自 javadoc

public void setBackground(颜色背景)

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

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

【讨论】:

  • 而且,正如我所说,很遗憾 Nimbus 选择忽略它。
  • 但情况更糟。文档说,只有当 setOpaque 为真时,它才会被尊重。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多