Reputation: 451
I'm trying to copy a symbol form an old java swing Application. This is the Old one:
And this is my attempt to copy this symbol:
beside that the two ellipses are not in the same dimension - If the Mouse isn't over the Textfield I want them to be displayed as Label but as soon as the mouse hovers about the Textfield it should show up.
Anyone any ideas how to implement ? Is there a css-style for something like this ?
My ( temporary ) solution looks like this:
public class CustomTextField {
private Group group;
private Label label;
private TextField textField;
public StdeTextField(String text){
label = new Label(text);
label.relocate(5,2.5);
textField = new TextField(text);
label.setOnMouseEntered(event -> {
group.getChildren().remove(label);
group.getChildren().add(textField);
textField.setText(label.getText());
});
textField.setOnMouseExited(event -> {
group.getChildren().remove(textField);
group.getChildren().add(label);
label.setText(textField.getText());
});
group = new Group();
group.getChildren().addAll(label);
}
public Group getGroup() {
return group;
}
}
The Label and the Text field has a offset, because I can't figure out how to get the Size of an Node if it's not rendered.
Upvotes: 2
Views: 113
Reputation: 82461
You could achieve this without having to replace the node using CSS only. There is one difference though: The text is still moved/clipped as in a fully visible TextField
:
group.getStyleClass().add("custom-text-field");
...
scene.getStylesheets().add("/my/stylesheet/location.css");
Unfortunately since :not()
is not available in javafx, we have to copy the default look over from modena.css. This allows us to hide the TextField
's decorations for TextField
, unless the group is hovered or the TextField
pressed (changing selection).
Stylesheet
/* "default" style when hovered/pressed */
.custom-text-field>.text-field:hover,
.custom-text-field>.text-field:pressed {
-fx-background-color: linear-gradient(to bottom, derive(-fx-text-box-border, -10%), -fx-text-box-border),
linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background);
-fx-highlight-fill: dodgerblue;
-fx-highlight-text-fill: white;
-fx-display-caret: true;
}
.custom-text-field>.text-field:hover:focused,
.custom-text-field>.text-field:pressed:focused {
-fx-background-color:
-fx-focus-color,
-fx-control-inner-background,
-fx-faint-focus-color,
linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background);
-fx-highlight-fill: dodgerblue;
-fx-highlight-text-fill: white;
-fx-display-caret: true;
}
/* Hide everything but text when neither hovered nor pressed */
.custom-text-field>.text-field,
.custom-text-field>.text-field:focused {
-fx-background-color:
null, null, null, null;
-fx-highlight-fill: null;
-fx-highlight-text-fill: black;
-fx-display-caret: false;
}
.custom-text-field:hover>.text-field:focused,
.custom-text-field>.text-field:pressed:focused {
-fx-background-color:
-fx-focus-color,
-fx-control-inner-background,
-fx-faint-focus-color,
linear-gradient(from 0px 0px to 0px 5px, derive(-fx-control-inner-background, -9%), -fx-control-inner-background);
-fx-highlight-fill: dodgerblue;
-fx-highlight-text-fill: white;
-fx-display-caret: true;
}
.custom-text-field>.text-field,
.custom-text-field>.text-field:focused {
-fx-background-color:
null, null, null, null;
-fx-highlight-fill: null;
-fx-highlight-text-fill: black;
-fx-display-caret: false;
}
If you want to go with your initial approach, you could simply make the TextField
invisible, instead of changing the contents of the group. This way layout is still done for it; it's just not rendered. Furthermore a binding could be used to synchronize text and visiblity:
label.textProperty().bind(textField.textProperty());
label.visibleProperty().bind(textField.visibleProperty().not());
// replace listeners with bindings to hover/pressed
textField.visibleProperty().bind(textField.hoverProperty().or(textField.pressedProperty()));
Upvotes: 3