I'm making login screen for a school project, and I want to give the user the ability to show and hide their password.
private PasswordField password;
How do I do this?
There can be many other ways to implement this feature, but below is the approach by using a custom skin (as suggested by Slaw).
The general idea for the approach is :
Please check the below demo: (style the button to the desired icon)
import com.sun.javafx.scene.control.skin.TextFieldSkin;
import javafx.application.Application;
import javafx.beans.binding.DoubleBinding;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Skin;
import javafx.scene.control.TextField;
import javafx.scene.control.ToggleButton;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class TogglePasswordFieldDemo extends Application {
@Override
public void start(Stage primaryStage) throws Exception {
StackPane root = new StackPane();
root.setPadding(new Insets(10));
Scene scene = new Scene(root, 320, 100);
primaryStage.setScene(scene);
primaryStage.setTitle("TogglePasswordField Demo");
primaryStage.show();
TogglePasswordField textField = new TogglePasswordField();
root.getChildren().add(textField);
}
class TogglePasswordField extends TextField {
@Override
protected Skin<?> createDefaultSkin() {
return new TogglePasswordFieldSkin(this);
}
}
class TogglePasswordFieldSkin extends TextFieldSkin {
ToggleButton show;
public TogglePasswordFieldSkin(TogglePasswordField textField) {
super(textField);
textField.setPadding(new Insets(4, 25.0, 4, 7));
show = new ToggleButton();
show.setFocusTraversable(false);
show.setMaxSize(15, 15);
show.setMinSize(15, 15);
show.setPadding(new Insets(0));
show.selectedProperty().addListener((obs, old, selected) -> {
// Resetting the text to invalidate the text property so that it will call the maskText method.
String txt = textField.getText();
int pos = textField.getCaretPosition();
textField.setText(null);
textField.setText(txt);
textField.positionCaret(pos);
});
show.translateXProperty().bind(new DoubleBinding() {
{
bind(textField.widthProperty(), show.widthProperty());
}
@Override
protected double computeValue() {
return (textField.getWidth() - show.getWidth()) / 2;
}
});
getChildren().add(show);
}
@Override
protected String maskText(String txt) {
if (show != null && !show.isSelected()) {
int n = txt.length();
StringBuilder passwordBuilder = new StringBuilder(n);
for (int i = 0; i < n; i++) {
passwordBuilder.append(BULLET);
}
return passwordBuilder.toString();
} else {
return txt;
}
}
}
}
PasswordFieldandTextFieldand toggle their visibility to simulate what you want. Or you can go all the way and implement a custom skin forPasswordField.