Issue
I am using validation that puts a red border around my TextFields
nameTF.setStyle("-fx-text-box-border: red;");
And set it back to default using
nameTF.setStyle("-fx-text-box-border: #D3D3D3;");
I am trying to use a CSS: Hoping to increase the width of the border so that the focused border is inside/or outside of my red validation border (so both show). Now when I click on a cell the selection border replaces the current border color and width...?
.text-input {
-fx-border-color: #D3D3D3;
-fx-border-width: 3 ;
}
.text-field:focused{
-fx-border-color: blue ;
-fx-border-width: 1 ;
}
Also, I have noticed that by using
.text-input {
-fx-border-color: #D3D3D3;
-fx-border-width: 3 ;
}
The red
nameTF.setStyle("-fx-text-box-border: red;");
doesn't show up at all?
What's Going on and what I am hoping for:
Thanks!
Solution
Suggested Approach
I suggest that you look at how controlsfx accomplishes this and either use that library or learn from their approach by studying their source code (if appropriate).
I checked the controlsfx validation code which applies style classes for validation feedback. The sample usage provides feedback via css drop shadow effects. This is a straightforward solution and easier than customizing backgrounds.
I tried this using a drop shadow effect to mark an invalid text field and it appeared to work well for me.
For complex controls other than text fields (like range sliders where the range tick text is also shadowed), the drop shadow approach looks a little weird, so perhaps for those, you may want to do something more sophisticated.
Example application
This sets or unsets an invalid
style class on a field as appropriate.
.invalid {
-fx-effect: dropshadow(three-pass-box, tomato, 3, 0.8, 0, 0);
}
A drop shadow effect is triggered when the invalid
style class is active, to provide the user with an indication that the field is invalid.
Refer to the CSS effect documentation to understand the settings for the dropshadow effect.
States
Invalid value with focus:
Invalid value without focus:
Valid value with focus:
Valid value without focus:
This sample is not meant as a robust validation framework, it is just an example to show how you might provide validation feedback styles for a text field.
The example operates based on a standard style class, but you could use a psuedo-class instead if you wanted to look into that. For example, similar to the :focus
psuedo-class, you could implement the CSS :invalid
psuedo-class.
import javafx.application.Application;
import javafx.geometry.*;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class ValidatorApp extends Application {
public static final String CSS = "data:text/css," + // language=CSS
"""
.invalid {
-fx-effect: dropshadow(three-pass-box, tomato, 3, 0.8, 0, 0);
}
""";
@Override
public void start(Stage stage) throws Exception {
TextField integerTextField = new TextField();
IntegerTextFieldValidator validator = new IntegerTextFieldValidator();
validator.validate(integerTextField);
integerTextField.textProperty().addListener(o ->
validator.validate(integerTextField)
);
VBox layout = new VBox(10,
labelField("Enter an integer: ", integerTextField),
labelField("Enter any value: ", new TextField("foobar"))
);
layout.setPadding(new Insets(10));
Scene scene = new Scene(layout);
scene.getStylesheets().add(CSS);
stage.setScene(scene);
stage.show();
}
HBox labelField(String labelText, Node field) {
HBox box = new HBox(10, new Label(labelText), field);
box.setAlignment(Pos.BASELINE_LEFT);
return box;
}
public static void main(String[] args) {
launch(args);
}
}
import javafx.scene.Node;
import javafx.scene.control.TextField;
public class IntegerTextFieldValidator {
private static final String INVALID_STYLECLASS = "invalid";
public void validate(TextField textField) {
String text = textField.getText();
if (text == null) {
setInvalid(textField);
return;
}
try {
Integer.parseInt(text);
setValid(textField);
} catch (NumberFormatException e) {
setInvalid(textField);
}
}
private void setInvalid(Node node) {
if (!node.getStyleClass().contains(INVALID_STYLECLASS)) {
node.getStyleClass().add(INVALID_STYLECLASS);
}
}
private void setValid(Node node) {
node.getStyleClass().removeAll(INVALID_STYLECLASS);
}
}
Answered By - jewelsea
Answer Checked By - Mary Flores (JavaFixing Volunteer)