oshatrk
oshatrk

Reputation: 529

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

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

Upvotes: 2

Views: 1000

Answers (1)

fabian
fabian

Reputation: 82461

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.

Upvotes: 3

Related Questions