Skip to content

Instantly share code, notes, and snippets.

@james-d
Last active December 28, 2015 19:19
Show Gist options
  • Save james-d/7549006 to your computer and use it in GitHub Desktop.
Save james-d/7549006 to your computer and use it in GitHub Desktop.
Example of using new Pseudoclass API in JavaFX 8.
package pseudoclasstest;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableMap;
import javafx.css.PseudoClass;
import javafx.geometry.HPos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.layout.ColumnConstraints;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;
public class PseudoClassExample extends Application {
@Override
public void start(Stage primaryStage) {
// Layout stuff (should be in FXML):
final GridPane root = new GridPane();
final TextField cityField = new TextField();
final ComboBox<String> countryCombo = new ComboBox<>();
final Label phoneFormatLabel = new Label();
phoneFormatLabel.setId("phone-format");
final TextField phoneField = new TextField();
phoneField.setId("phone-field");
final Button button = new Button("OK");
root.addRow(0, new Label("City:"), cityField);
root.addRow(1, new Label("Country:"), countryCombo);
root.addRow(2, new Label("Telephone:"), phoneField, phoneFormatLabel);
root.addRow(3, new Label(), button);
ColumnConstraints leftCol = new ColumnConstraints();
ColumnConstraints rightCol = new ColumnConstraints();
leftCol.setHalignment(HPos.RIGHT);
rightCol.setHalignment(HPos.LEFT);
root.getColumnConstraints().addAll(leftCol, rightCol);
// Controller stuff:
final ObservableMap<String, String> formats = FXCollections.observableHashMap();
formats.put("UK", "(01234) 123456");
formats.put("USA", "(123) 456-7890");
final Map<String, Pattern> regexps = new HashMap<>();
regexps.put("UK", Pattern.compile("\\(0[1-9]\\d{2,5}\\)\\s*[1-9]\\d{5,}"));
regexps.put("USA", Pattern.compile("\\([1-9]\\d{2}\\)\\s*\\d{3}-\\d{4}"));
countryCombo.getItems().addAll(formats.keySet());
countryCombo.getSelectionModel().select(0);
phoneFormatLabel.textProperty().bind(
Bindings.concat("Format: ",
Bindings.stringValueAt(formats, countryCombo.valueProperty())));
final PseudoClass invalidClass = PseudoClass.getPseudoClass("invalid");
final BooleanProperty valid = new SimpleBooleanProperty();
valid.bind(Bindings.createBooleanBinding(
() -> regexps.get(countryCombo.getValue()).matcher(phoneField.getText()).matches(),
countryCombo.valueProperty(), phoneField.textProperty()));
final ObservableValue<Boolean> invalid = valid.not();
invalid.addListener((obs, oldValue, newValue) -> root.pseudoClassStateChanged(invalidClass, invalid.getValue()));
root.pseudoClassStateChanged(invalidClass, invalid.getValue());
button.disableProperty().bind(invalid);
// Application stuff:
Scene scene = new Scene(root, 480, 260);
scene.getStylesheets().add(getClass().getResource("pseudoClassTest.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args) {
launch(args);
}
}
.root {
-fx-padding: 10px ;
-fx-hgap: 5px ;
-fx-vgap: 5 px ;
}
.root:invalid #phone-field {
-fx-background-color: red ;
}
.root:invalid #phone-format {
-fx-text-fill: red ;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment