Skip to content

Text Styles: Inline, Style Class, and Custom Style Objects

JordanMartinez edited this page Nov 3, 2017 · 4 revisions

CSS Styles

When we say style, we mean CSS style. For example, the JavaFX CSS Reference Guide for a Text object shows that it can be styled in a variety of ways:

.text {
    /* Some CSS from Text itself */
    -fx-font: <font>;
    -fx-text-alignment: <alignment>;

    /* CSS inherited from Shape */
    -fx-fill: <paint>;
    -fx-stroke: <paint>;

    /* CSS inherited from Node */
    -fx-cursor: <cursor>;
    -fx-rotate: <number>;
}

Thus, there are two ways to style a Text object.

  1. via inline CSS styling: text.setStyle("-fx-text-alignment: right;");
    • This is useful for applying a specific style to only one instance.
  2. via CSS style classes: text.getStyleClass().add("right-aligned-text"); where a style sheet with .right-aligned-text { -fx-text-alignment: right; } is added to the scene graph.
    • This is useful for applying a specific style to all instances of a class or styling things by category.

Applying Styles

In GenericStyledArea (the base area which other areas subclass), one must denote what object should be used for the text's style and supply an applyStyle BiConsumer. In other words, when given a text object and its style object, how should it be styled? There are a number of ways to style it:

  1. If you don't have a custom style object and merely want to style each Text object separately, you should just use InlineCssTextArea. Its style object is String and its applyStyle is (Text text, String cssStyleString) -> text.setStyle(cssStyleString);
  2. If you don't have a custom style object and have text that should be styled according to certain categories (think code editors highlighting keywords in the language), you should use StyleClassedTextArea or CodeArea (a subclass of StyleClassedTextArea). Its style object is Collection<String> and its applyStyle is (Text text, Collection<String> styleClasses) -> text.getStyleClass().addAll(styleClasses)
  3. If you want to use your own custom style object, please see the next section.

Implementing a Custom Style Object

Before thinking of how to design the object, think about how you will apply it. The required applyStyle BiConsumer can still follow the InlineCssTextArea approach (via setStyle(String)), the StyleClassedTextArea appraoch (via getStyleClass().addAll(styleClasses)), or a mixture of the two.

If creating a custom style object that will follow the InlineCssTextArea approach, one should follow this pattern:

public class CustomObject {
    // example fields: use your own in implementation
    private final boolean useRedText;
    private final int rotate;

    // getters, setters, & constructors

    String toCss() {
        String css = useRedText ? "-fx-font-color: red;" : "";
        return css + "-fx-rotation: " + rotate + ";";
}

// apply style would look like
(Text text, CustomObject style) -> text.setStyle(style.toCSS());

If creating a custom style object that will follow the StyleClassedTextArea approach, one should follow this pattern:

public class CustomObject {
    // example fields: use your own in implementation
    private final boolean includeRedText;
    private final boolean includeCaretHand;

    // getters, setters, & constructors

    private void calculateListSize() {
        int size = includeRedText ? 1 : 0;
        size += includeCaretHand ? 1 : 0;
        return size;
    }

    Collection<String> toList() {
        List<String> list = new ArrayList(calcualteListSize());
        if (includeRedText) { list.add("red-text"); }
        if (includeCaretHand) { list.add("text-with-caret"); }
        return list;
}

// apply style would look like
(Text text, CustomObject style) -> text.getStyleClass().addAll(style.toList());

If you wish to use an approach that mixes the two, you should follow this pattern:

public class CustomStyleObject {
    // example fields: use your own in implementation
    private final boolean useRedText;
    private final int rotation;
    private final String backgroundStyleClass

     // getters, setters, & constructors removed for brevity
}
 
// then use this BiConsumer as your applyStyle
(Text text, CustomStylObject style) -> {
    // apply a style class first
    text.getStyleClass().add(style.getBackgroundStyleClass());
    // selectively apply css that overrides style class
    String cssStyle = "";
    if (style.isUseRedText() {
        cssStyle = "-fx-font-color: red;"
    }
    cssStyle = cssStyle + "-fx-rotation: " + rotation + ";";
    text.setStyle(cssStyle);
}

// then you would write in your project
CustomStyleObject style = new CustomStyleObject(true, 40, "red-text");
int from = 10;
int to = 30;
area.setStyle(from, to, style);

Style Class Pattern

This section merely shows the code pattern one must use to style text via style classes:

// in your code
StyleClassedTextArea area = // creation code;
List<String> styleClasses = Arrays.asList("red-text", "text-with-caret");
int from = 10;
int to = 30;
area.setStyle(from, to, styleClasses);

// in your Application
Scene scene = // creation code
scene.getStyleSheets().add(YourCustomAreaObject.class.getResource("custom-styles.css").toExternalForm());

In a separate file called "custom-styles.css":

.red-text {
    -fx-font-color: red;
}
.text-with-caret {
    -fx-font-cursor: hand;
}