Giordano Agostini
Giordano Agostini

Reputation: 51

Do you know method to get the JavaFX Text node of a TextArea without using the CSS properties?

I wish to find a method to get the Text node of a TextArea without using the CSS properties. The Text node of JavaFX exposes the method setUnderline(boolean) through which I can set the underline property of a TextArea; the TextArea, instead, doesn't expose the same method. In addition, the TextArea.getText() method returns a String instead of a Text object. So, I solved the problem as follow: In the code,

// Fields..
private final PseudoClass pseudoClass = PseudoClass.getPseudoClass("underlined");
private final SimpleBooleanProperty underlinedProperty = new SimpleBooleanProperty(false);
private final TextArea textArea = new TextArea();

[...]

// In a method (ex. in the constructor)..
{
    textArea.setId("textArea"); 
    underlinedProperty.addListener(new ChangeListener<Boolean>() {
        @Override
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
            Node node = textArea.getScene().lookup("#textArea .text");  
            node.pseudoClassStateChanged(pseudoClass, newValue);
        }
    });
}

[...]

// The class exposes the getter method for the underlinedProperty
public SimpleBooleanProperty getUnderlinedProperty() {
    return underlinedProperty;
}

Now, I've create a CSS sheet with this code:

#textArea .text {
    /* some styles */
    -fx-underline: false;
}

#textArea .text:underlined {
    -fx-underline: true;
}

Finally, the above class is called in some other classes:

{
    'handleOfClassInPoint1'.getUnderlineProperty().set(true); // or false
}

The problem is the lookup() method: this method returns a not null value only if all the fx nodes were created, i.e. only after some graphical result. I wish to find a procedure to set the underline property of a TextArea without using CSS (ex. a toggle button manages the underline property: the text of a TextArea is underlined if the toggle is selected). Anyone can help me? Thank you so much!

Upvotes: 2

Views: 711

Answers (1)

Slaw
Slaw

Reputation: 45806

Based on your description in the question comments, I would recommend the following.

Create a custom TextArea that looks something like this:

public class CustomTextArea extends TextArea {

    private static final PseudoClass UNDERLINED = PseudoClass.getPseudoClass("underlined");

    private final BooleanProperty underlined = new SimpleBooleanProperty(this, "underlined") {
        @Override
        protected void invalidated() {
            pseudoClassStateChanged(UNDERLINED, get()); // update PseudoClass state to match 
                                                        // the current value of the property
        }
    };

    // property access methods

    public final void setUnderlined(boolean underlined) {
        this.underlined.set(underlined);
    }

    public final boolean isUnderlined() {
        return underlined.get();
    }

    public final BooleanProperty underlinedProperty() {
        return underlined;
    }

    // constructor      

    public CustomTextArea(String text, boolean underlined) {
        super(text);
        setUnderlined(underlined);
        getStyleClass().add("custom-text-area"); // to allow specific CSS styling
    }

}

Then in your CSS you would do:

.custom-text-area .text {
    -fx-underline: false;
}

.custom-text-area:underlined .text {
    -fx-underline: true;
}

The CSS is set on any Text node that is a descendant of aCustomTextArea. The first CSS rule (the one without ":underlined") may not even be necessary since the default of -fx-underline for a Text node is false.

Then to query whether or not the text is underlined is a simple matter of calling area.isUnderlined() where area is an instance of CustomTextArea.

To maintain the correct visual state you could bind the underlined property of the CustomTextArea bidirectionally to the selected property of a ToggleButton. When one changes the other will reflect that change.

If you want to style only a specific CustomTextArea then you can still give it an ID and reference it in the CSS with #ID.

Upvotes: 1

Related Questions