如何强制我的 JavaFX 应用程序中的所有按钮使用我的自定义皮肤?

How to force my custom skin to be used by all buttons in my JavaFX application?

假设我为 Button 编写了一个新皮肤。
在 JavaFX 8 中,它看起来像:

import com.sun.javafx.scene.control.skin.ButtonSkin;

// This is quite dirty because of using non-stable api:
public class MyButtonSkin extends ButtonSkin {
    ...
}

然后我希望在我的应用程序中为 FXMLLoader 创建的每个按钮使用这个皮肤(通过 <Button ...> fxml-element) 我不想更改 fxml 文件。

我的问题是:

在 JavaFX 8 中有哪些可能性?

可以使用一些 DI 框架来做到这一点吗?

JavaFX 9 呢?


附加代码示例:

此皮肤为按钮引入了新的 underkeypress 伪类:

import com.sun.javafx.scene.control.skin.ButtonSkin;
import javafx.css.PseudoClass;
import javafx.scene.control.Button;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;

public class MyButtonSkin extends ButtonSkin {
    private static final PseudoClass PSEUDO_CLASS_UNDERKEYPRESS = PseudoClass.getPseudoClass("underkeypress");

    public MyButtonSkin(Button button) {
        super(button);
        button.addEventFilter(KeyEvent.KEY_PRESSED,
                (event -> {
                    if (event.getCode() == KeyCode.SPACE) {
                        pseudoClassStateChanged(PSEUDO_CLASS_UNDERKEYPRESS, true);
                    }
                }));
        button.addEventFilter(KeyEvent.KEY_RELEASED,
                (event -> {
                    if (event.getCode() == KeyCode.SPACE) {
                        pseudoClassStateChanged(PSEUDO_CLASS_UNDERKEYPRESS, false);
                    }
                }));
    }
}

应该通过 CSS 使用该伪类,例如:

.button:underkeypress {
    -fx-base: red;
}

正如@kleopatra 指出的那样,将皮肤应用于场景中所有 Button 的最佳方法是使用 CSS 样式表。

.button {
    -fx-skin: "my.package.MyButtonSkin";
}

将此样式表应用于场景的根

Parent root = loader.load(); // load fxml
root.getStylesheets().add(getClass().getResource("style.css").toExternalForm());

据我所知,在 JavaFX 9 中没有更简单的方法可以做到这一点。唯一的区别是 ButtonSkin 被移动到 public API,请参阅 javafx.scene.control.skin.ButtonSkin