我想向我的自定义标签添加自定义 CSS 整数属性(在此示例中我使用-fx-foo
)。这是我的代码:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.IntegerProperty;
import javafx.css.CssMetaData;
import javafx.css.Styleable;
import javafx.css.StyleableIntegerProperty;
import javafx.css.converter.SizeConverter;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class NewMain extends Application {
public static class FooLabel extends Label {
private static final CssMetaData<FooLabel, Number> FOO_PROPERTY = new CssMetaData<FooLabel, Number>("-fx-foo",
SizeConverter.getInstance(), 10) {
@Override
public boolean isSettable(FooLabel label) {
return true;
}
@Override
public StyleableIntegerProperty getStyleableProperty(FooLabel label) {
return (StyleableIntegerProperty) label.fooProperty();
}
};
private static final List<CssMetaData<? extends Styleable, ?>> CSS_META_DATA;
static {
List<CssMetaData<? extends Styleable, ?>> list = new ArrayList<>(Label.getClassCssMetaData());
list.add(FOO_PROPERTY);
CSS_META_DATA = Collections.unmodifiableList(list);
}
public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
return CSS_META_DATA;
}
private final StyleableIntegerProperty foo = new StyleableIntegerProperty(10) {
@Override
public CssMetaData getCssMetaData() {
return FOO_PROPERTY;
}
@Override
public Object getBean() {
return FooLabel.this;
}
@Override
public String getName() {
return "foo";
}
};
public FooLabel() {
super();
foo.addListener((observable, oldValue, newValue) -> {
System.out.println("NEW VALUE:" + newValue);
});
}
public IntegerProperty fooProperty() {
return foo;
}
public void setFoo(int foo) {
this.foo.set(foo);
}
public int getFoo() {
return foo.get();
}
}
/**************** MAIN APP *****************/
@Override
public void start(Stage primaryStage) {
var fooLabel = new FooLabel();
fooLabel.getStyleClass().add("test");
fooLabel.setText("abc");
VBox root = new VBox(fooLabel);
root.getStylesheets().add(NewMain.class.getResource("test.css").toExternalForm());
Scene scene = new Scene(root, 100, 100);
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
和 CSS:
.test {
-fx-foo: 100;
-fx-background-color: yellow;
}
代码已编译,运行时不会抛出任何异常。标签为黄色。但是,foo
属性从未改变,似乎-fx-foo
只是被忽略了。有人能说说如何修复它吗?
可从 CSS 实现样式的类型
Styleable
。为了让 CSS 引擎知道哪些属性是可样式的,Styleable
必须报告其 CSS 元数据。它通过其getCssMetaData()
方法执行此操作。请注意,这是一个实例方法。如果您有自己的类型及其自己的 CSS 元数据,则必须覆盖该方法。如果要使所有可样式的属性继续正常工作,则返回的列表应包含超类型和您自己的类型的 CSS 元数据。这就是大多数可样式化类定义的静态
getClassCssMetaData()
方法发挥作用的地方。系统并不严格要求它,而且事实上,由于方法是静态的,编译器也无法强制执行它(Java 中没有办法规定类型必须有静态方法)。但它基本上是预期 API 的一部分,并且至少提供两个功能:它使子类型可以轻松地以静态方式获取其超类型的元数据,而无需反射(请注意,由于 CSS 元数据在类的所有实例之间共享,因此静态定义它是有意义的)。
它允许工具检查 CSS 元数据,而无需实例化类。
该
getCssMetaData()
实现通常委托给静态方法。但是,您实际上想要重写
Control#getControlCssMetaData()
从 继承的类型Control
。它提供与 相同的功能Styleable#getCssMetaData()
,但Control
已经提供了后者的最终实现。该实现结合了Control#getControllCssMetaData()
和 的CSS 元数据SkinBase#getCssMetaData()
,允许皮肤添加自己单独的可设置样式的属性。因此,您只需将以下内容添加到您的
FooLabel
课程中:注意:方法在
protected
中Control
,但Labeled
类使其成为public
。完整示例
源代码
FooLabel.java
实现方式与标准控件实现可样式化属性的方式类似。但请注意,它使用StyleablePropertyFactory来创建
CssMetaData
。主程序
输出