我尝试为我的组件创建一个自定义 CSS 样式属性,其中包含多个颜色值,例如 -fx-background-color。但是我遇到了问题,尽管我定义了类似于 -fx-background-color 属性的 CSS 属性,但只有第一个颜色值会从 CSS 声明中解析出来。以下是 CSS 声明:
.default-chart-theme {
-jfc-default-paint-sequence: red,white,green,blue,yellow,orange,gray;
}
这是 java 类中的 CssMetadata 声明:
public final CssMetaData<StyleableChartViewer, Paint[]> DEFAULT_PAINT_SEQUENCE = new CssMetaData<>("-jfc-default-paint-sequence", PaintConverter.SequenceConverter.getInstance(), new Paint[] { Color.RED } )
{
@Override
public boolean isSettable(StyleableChartViewer styleable)
{
return !cssDefaultPaintSequence.isBound();
}
@Override
public StyleableProperty<Paint[]> getStyleableProperty(StyleableChartViewer styleable)
{
return cssDefaultPaintSequence;
}
};
public final SimpleStyleableObjectProperty<Paint[]> cssDefaultPaintSequence =
new SimpleStyleableObjectProperty<>(DEFAULT_PAINT_SEQUENCE, this, "cssDefaultPaintSequence", new Paint[] { Color.RED } );
在 getCssMetaData 中,我也返回了此属性,并且它也被解析,但不是绘画序列,而是仅将其解析为单个颜色值。
处理 css 属性时我也收到警告:
WARNING: Caught 'java.lang.ClassCastException: class javafx.scene.paint.Color cannot be cast to class [Ljavafx.css.ParsedValue; (javafx.scene.paint.Color and [Ljavafx.css.ParsedValue; are in unnamed module of loader 'app')' while converting value for '-jfc-default-paint-sequence' from rule '*.default-chart-theme' in stylesheet
欢迎任何关于如何创建此类 CSS 属性的建议。我尝试过 Google,也尝试过使用 Perplexity 获取一些关于此问题的信息,但没有找到任何有用的解决方法。
谢谢!
部分解决方案
一种解决方案是创建您自己的
StyleConverter
实现,并在 CSS 中引用颜色列表。通过引用颜色列表,转换器将以单个字符串的形式接收值,然后您可以按照自己的意愿进行处理。遗憾的是,这种方法的一个显著缺点是变量(即查找的颜色)不会被解析,而且您无法在样式转换器内部解析它们。也许有更好的方法。如果有的话,希望其他人能发表答案。
例子
此示例仅能解析
Color
,而不能解析任意Paint
。因此,这只是一个“部分解决方案”,尽管应该可以对其进行修改,使其能够像原生工作方式一样解析渐变和图像模式(这并非微不足道的修改)。换句话说,应该可以使这种方法像 这样的属性一样灵活-fx-background-color
,尽管无需解析任何变量。主程序
颜色序列转换器.java
颜色区域.java
你的尝试为何失败
A
StyleConverter
负责获取 aParsedValue
并将其转换为 JavaFX 属性所使用的类型。但是 aParsedValue
表示的值是已经被CSS 解析器解析过的值。换句话说,该值已经被解析为一个中间对象。此外, aParsedValue
可能还关联了它自己的转换StyleConverter
器。如果我没记错的话,该转换器始终优先于与可样式化属性关联的转换器CssMetaData
。将值解析成哪个中间对象,以及解析后的值关联到哪个转换器(如果有的话),这些都无法自定义。解析器的行为是硬编码的。检查链接的代码,你就能发现你的尝试中出了什么问题。
您的 CSS 属性
-jfc-default-paint-sequence
不是特殊处理的属性之一。您的属性值不是数字、时长、哈希值、函数或 URL。它也不是已知常量或先前定义的变量。这意味着该值将被视为简单的字符串/可能的颜色。但是,在这种情况下,仅考虑第一个“项”。在您的示例中,第一个“项”是
red
。所有其他“项”(其他颜色)都将被忽略。示例值的第一个“项”是
red
,它可以解析为 aColor
(具体来说,不是任何Paint
类型)。因此,该值被解析为 aColor
,并包装在单个ParsedValue<Color, Color>
中返回。这ParsedValue
没有关联的StyleConverter
。期望
PaintConverter.SequenceConverter
一个ParsedValue<ParsedValue<?, Paint>[], Paint[]>
。因此,ClassCastException
当尝试获取 的值时会出现aParsedValue
,因为它期望一个 ,ParsedValue<?, Paint>[]
但却得到了一个Color
。由于此行为是硬编码的,很遗憾您无法更改它。在这种情况下,如果解析器处理的是绘制数组,那其实无关紧要,但事实并非如此(有趣的是,解析器确实处理了数字数组的大小)。
现在,如果值无法解析为 a
Color
,则会得到ParsedValue<String, String>
不带 的aStyleConverter
。这就是上述“部分解决方案”的优势所在。通过引用该值,CSS 解析器会将整个值视为一个单独的“术语”。该“术语”无法解析为颜色。这导致 CSS 元数据StyleConverter
基本上完全控制了该值的解析方式。