1

Suppose I wrote a new skin for Button.
In JavaFX 8 it can look like:

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

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

Then I wish to use this skin in my application for every button created by FXMLLoader (via <Button ...> fxml-element) and I don't want to change fxml-files.

My questions are:

What are possibilities to do this in JavaFX 8?

Can be some DI-framework used to do this?

And what about JavaFX 9?


Additional code example:

This skin introduces new underkeypress pseudoclass for buttons:

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);
                    }
                }));
    }
}

That pseudoclass should be used via CSS like:

.button:underkeypress {
    -fx-base: red;
}
oshatrk
  • 499
  • 3
  • 14

1 Answers1

3

As @kleopatra noted the best way to apply the skin to all Buttons in your scene is using a CSS stylesheet.

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

apply this stylesheet to the root of the scene

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

AFAIK there is no easier way in JavaFX 9 for this. The only difference is that ButtonSkin was moved to the public API, see javafx.scene.control.skin.ButtonSkin.

fabian
  • 80,457
  • 12
  • 86
  • 114
  • Thanks! I only wish to mention the stylesheet can be loaded for whole application with `Application.setUserAgentStylesheet(Application.STYLESHEET_MODENA); StyleManager.getInstance().addUserAgentStylesheet(getClass().getResource("style.css").toExternalForm());` before of creation of any `FXMLLoader` instances. – oshatrk Apr 09 '18 at 11:28