11

我有一个应用程序在几个地方使用禁用的 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); }

例子

替代文字

4

4 回答 4

17

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

灵气不透明错误

对我有用的解决方法是:

myPane.setOpaque(false); // added by OP
myPane.setBorder(BorderFactory.createEmptyBorder());
myPane.setBackground(new Color(0,0,0,0));

来自 OP 的注释:我还必须确保 JTextField 的 setOpaque(false) 以便绘制父背景 - 只是想向其他跟随者提及这一点,以防他们像我一样尝试过 setOpaque(true)。

于 2009-03-05T17:25:59.170 回答
0

嘿,软件猴子。

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

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

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

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

于 2009-03-05T04:56:58.190 回答
0

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


OP的反驳

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

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

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

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

于 2009-03-06T13:08:23.663 回答
0

来自 javadoc

公共无效 setBackground(颜色背景)

设置此组件的背景颜色。仅当组件不透明时才使用背景颜色,并且仅由 JComponent 或 ComponentUI 实现的子类使用。JComponent 的直接子类必须覆盖paintComponent 以遵守此属性。

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

于 2009-03-06T13:28:18.250 回答