在 javaFX TextField 中设置文本颜色 "Without using CSS"

Setting text color in javaFX TextField "Without using CSS"

如果你要建议 CSS 那就别费心了,我知道它很好用而且很容易使用,这只是出于好奇,因为我讨厌和 [=38 打交道=] 在 Java.

中编码

JavaFX TextField 间接扩展了 Parent,它有一个 "unmodifiable" ObservableList of children 类型的节点,其中之一必须是文本类型,所以我已经扩展了 TextField class 并编写了两个方法来检查,这个方法从 TextField 中获取所有 children。

public ArrayList<Node> getAllChildren(Parent parent) {
    ArrayList<Node> res = new ArrayList<Node>();
    for (Node n : parent.getChildrenUnmodifiable()) {
        if (n instanceof Parent) {
            res.addAll(getAllChildren((Parent) n));
        } else {
            res.add(n);
        }
    }
    return res;
}

这个是打印结果的

public void printChildren() {
    ArrayList<Node> nodes = getAllChildren(this);
    System.out.println("size = "+nodes.size()+" {");
    for (Node n : nodes) {
        System.out.println("    "+n.getClass().getSimpleName());
    }
    System.out.println('}');
}

结果和预期的一样。

size = 3 {
    Path
    Text
    Path
}

所以我写了这个方法来只获取文本object。

private Text findText(Parent parent) {
    for (Node n : parent.getChildrenUnmodifiable()) {
        if (n instanceof Text) {
            return (Text) n;
        } else if (n instanceof Parent) {
            Text p = findText((Parent) n);
            if (p != null) {
                return p;
            }
        }
    }
    return null;
}

它工作正常并返回了文本 object。

所以我只需要设置填充就可以了。

public void setTextFill(Paint p) {
    findText(this).setFill(p);
}

但是每当我尝试设置 textFill 时,我都会收到一个 RuntimeException,上面写着:

Text.fill : A bound value cannot be set

仅设置文本颜色有点长。

感谢任何形式的帮助。

Control 的内部结构是有意隐藏的。在这种情况下,Text 节点的文本填充使用绑定保持最新。除非在设置之前解绑节点的fill属性(text.fillProperty().unbind())否则设置值会失败

如果你想和他们打交道,你应该使用 Skin。假设您使用 JavaFX 版本 9 或更高版本,TextField 的皮肤是 public API 的一部分,您可以通过扩展它来访问 textFill 属性:

@Override
public void start(Stage primaryStage) {
    TextField textField = new TextField();

    textField.setSkin(new TextFieldSkin(textField) {
        {
            // use red color for text
            setTextFill(Color.RED);
        }

    });

    StackPane root = new StackPane(textField);

    Scene scene = new Scene(root, 500, 500);

    primaryStage.setScene(scene);
    primaryStage.show();
}

如果您想要 TextField 的子类型和 public fill 属性,请将这样的 JavaFX 属性 添加到您的子类并覆盖 createDefaultSkin 方法到 return TextFieldSkin 的子类,为其 textFill 属性.

创建绑定