如何强制我的 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
。
假设我为 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
。