LookAndFeel-独立的颜色键参考
我目前正在为我工作的公司的产品开发一组自定义控件。为此,我扩展了许多 Swing 控件,并重写了许多 paint
方法。
为了保持一致的配色方案,我使用 UIManager.getColor
接收 paint
、setBackground
等方法的颜色。
这一切都很好,直到我们注意到当前 JRE 版本附带的 Nimbus LookAndFeel 使用完全不同的颜色键,因此许多东西看起来完全不合适。
例如,虽然所有其他库存 LookAndFeels(Metal、Windows Classic、Windows、CDE/Motif、GTK)已将键“text”定义为文本和“textText”的明亮背景< /em>作为对应的前景色,Nimbus中的“text”实际上是黑色前景色,标准的文本背景色似乎不存在。
“TextField.background”可以工作,但是,例如,对于 Windows LookAndFeels 来说,它并不存在。
我想你现在已经明白问题所在了。我不想为每个 LAF 维护一组颜色键,谁知道将来会添加哪些 LAF 以及我的公司可能决定使用哪些 LAF。
当然,一个简单的解决方案是摆脱 Nimbus,但可以理解的是,我的老板根本不喜欢这个想法,而且 Nimbus 现在是 JRE 的一部分,应该得到支持。
所以我想知道是否有任何标准化方法来获取依赖于 LAF 的颜色,例如“文本背景/前景”、“选定的文本 bg/fg”等?
I am currently working on a set of custom controls for a product of the company I'm working in. For this, I am extending a lot of Swing controls and also overriding a lot of paint
methods.
In order to maintain a consistent color scheme, I receive the colors for my paint
, setBackground
etc. methods using UIManager.getColor
.
This was perfectly fine until we noticed that the Nimbus LookAndFeel, which is shipped with current JRE versions, uses totally different color keys, thus many things looks totally out of place.
For instance, while all other stock LookAndFeels (Metal, Windows Classic, Windows, CDE/Motif, GTK) have defined the key "text" as a bright background for texts and "textText" as the corresponding foreground color, "text" in Nimbus is actually a black foreground color, and a standard text background color does not seem to exist.
"TextField.background" would work, but that, for instance, doesn't exist for the Windows LookAndFeels.
I suppose you get the problem by now. I don't want to have to maintain a set of color keys for each LAF, who knows what LAFs will be added in the future and which my company may decide to use.
A simple solution would be getting rid of Nimbus, of course, but understandably my boss doesn't like this idea at all, besides Nimbus is part of the JRE these days and should be supported.
So I wonder whether there is any standardized way to get LAF-dependent colors like, say, "text background / foreground", "selected text bg/ fg", etc.?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我不确定是否有一种“标准化”的方法来获取这些值。
正如您所注意到的,Nimbus 使用自己的名称作为颜色。具体来说,属性
textForeground
和textBackground
。这种奇怪的现象可能是因为 Nimbus 使用了一小部分基本颜色(在图表中列为主要颜色),其中有根据它们计算出的辅助颜色,进而用作所有剩余颜色的基础。
I'm not sure that there is a "standardized" way of getting these values.
As you noticed, Nimbus uses its own names for colors. Specifically, the properties
textForeground
andtextBackground
.This oddness is likely because Nimbus uses a small selection of basic colors (listed as Primary in the chart), which have Secondary colors calculated from them, which in turn are used as the basis for all the remaining colors.
是的,正如 @josefx 所暗示的那样,不幸的是,这不是 UI 的工作方式。它们不是一组通用的可移植属性,而是一组实际的组件和每个组件的特定实现。它并不是一个真正对自定义组件友好的可扩展系统。
抽象级别是组件,而不是更细粒度的东西。如果您尝试为 L&F 不了解的组件请求 ComponentUI,那么您就不走运了。 ComponentUI 只不过是绘制方法的包装器,因此它根本没有义务公开任何元数据。
简而言之,您基本上只能执行 josefx 建议的 JTextField(或其他一些适当的组件)“颜色刮擦”技术,或者在代码中添加特定支持来处理您希望的 L&F 属性名称的偏心率好好支持。
另一个建议是“先发制人”L&F 更改,并对您希望支持的 L&F 进行子类化,以使您的组件在这些 L&F 中更像是一等公民。当 L&F 更改为您支持的 L&F 时,默默地将其类名与您的子类类名切换,然后为您的自定义组件实现 ComponentUI,并扩展父级 LookAndFeel.createUI 方法,使其“知道”关于您的新组件。
这些都不是很漂亮,但是 Swing 组件系统并不是设计为可在运行时扩展以处理自定义组件的。创建 L&F 时,整个组件套件一次性完成。
Yea, as @josefx implied, unfortunately this isn't how the UIs work. They're not a pool of generic portable properties, rather they're a set of actual components and specific implementations for each of those components. It's not really an extensible system that's friendly to custom components.
The level of abstraction IS the component, not something finer grained. If you try to ask for a ComponentUI for a component that the L&F does not know about, you're out of luck. And the ComponentUI is little more than a wrapper for a paint method, so it's not obligated to expose any meta data at all.
Simply put, you're stuck basically doing the JTextField (or some other appropriate component) "color scrape" technique that josefx suggests, or adding specific support in your code to handle the eccentricities of the property names of the L&F's that you wish to support well.
Another suggestion is to "pre-empt" the L&F change, and subclass the L&Fs you wish to support to make your components more of a first class citizen within those L&Fs. When the L&F changes to a L&F that you support, silently switch out their class name with your subclasses class name, and then implement ComponentUIs for your custom components, and extend the parent LookAndFeel.createUI method so that it "knows" about your new components.
None of these are pretty, but the Swing component system isn't designed to be extensible at run time to handle custom components. The entire component suite is done all at once when the L&F is created.
没有办法解决这个问题 - 您必须为颜色名称(以及可能的其他属性名称)创建自己的抽象层。
基本上,您有使用自己的颜色名称的库存 LookAndFeels(Metal、Windows Classic、Windows、CDE/Motif、GTK)和使用不同名称的 Nimbus。
创建一个类,例如
LafProperties
,以便为每个属性/颜色提供方法(例如“getTextColor”)。此类返回经典 Laf 样式的属性。然后为 Nimbus 扩展此类,并仅更改 Nimbus 中不同的方法。如果普通 Lafs 和 Nimbus 的大多数属性的名称不同,那么您可以使用一个接口和两个实现类。
There is no way around it - you have to create your own abstraction layer for color names (and possibly other property names).
Basically you have stock LookAndFeels (Metal, Windows Classic, Windows, CDE/Motif, GTK) that use their own color names and Nimbus that uses different names.
Create a class e.g.
LafProperties
so that for each property/color you have method (e.g. "getTextColor"). This class returns properties for classic Laf styles. Then extend this class for Nimbus, and change only methods that differ in Nimbus.If stock Lafs and Nimbus have most of the properties differently named, than use you might use an interface and two implementing classes.
这不是一个好方法,但它应该适用于基础知识:
更新:
ComponentUI 类及其子类,它们是所有外观的基类仅提供初始化 laf 相关默认值的方法,它们没有提供访问这些值的直接方法。
Not a nice way but it should work for the basics:
Update:
The ComponentUI class and its subclasses which are the base classes for all look and feels only provide a method to initialise the laf dependent default values, they provide no direct way to access these values.
java.awt.SystemColor 类提供变量对于很多共同的属性。
对于文本前景/背景,请使用成员字段
text
/textText
;对于选定的文本,请使用textHighlight
/textHighlightText
。The java.awt.SystemColor class provides variables for a lot of the common attributes.
For text foreground/background use the member fields
text
/textText
; for selected text, usetextHighlight
/textHighlightText
.读到你的问题时,我的脑海中浮现出一些事情,如果我感觉良好的话,这会有点令人沮丧:
因此最终:
Few things ppop into my mind reading your question, which is a tad spiced with underbelly frustration if I have sensed well:
And thus ultimately: