如何取消屏蔽 JavaFX 密码字段或正确屏蔽文本字段?

问题描述 投票:0回答:7

在我的用户界面中,我有一个像这样的PasswordFieldurm底部的那个!):

Login dialog with JavaFX PasswordField

我希望用户能够选中您在图片中看到的复选框并显示所有“秘密”密码字符。与我们从许多现代的询问密码的 UI 中获得的选项没有太大区别。 但是,我在 JavaFX API 中找不到任何可以让我这样做的东西?

如果我的担忧成立,那么我想使用一个

TextField
来显示按下的最后一个键仅半秒或直到按下下一个键,然后他将屏蔽所有以前的用户输入。这会产生一种很酷的动画效果,有时可以在现代 UI 中看到。但是,有没有办法让我掌握依赖于操作系统的(我认为它依赖于操作系统??)我应该使用密码回显字符?

如果无法获得与操作系统相关的字符,那么我很乐意使用您在图片上看到的字符(Windows 8 计算机上的 JavaFX)。这个陌生人的 UTF-8 代码点是什么?

utf-8 javafx-2 textfield password-protection
7个回答
47
投票

> 但是,我在 JavaFX API 中找不到任何可以让我这样做的东西?

PasswordField
组件默认不显示屏蔽文本。但是,您可以将
PasswordField
TextField
一起使用,并分别使用这些组件切换屏蔽/未屏蔽文本。未屏蔽的文本由
TextField
显示,如下面的示例演示所示。

>我想使用一个 TextField 来显示最后一个按下的键仅半秒或直到按下下一个键,然后他将屏蔽所有以前的用户输入。

由于

PasswordField
,本身就是
TextField
的扩展版本。您始终可以使用您提到的属性构建自己的自定义密码文本框。

>有没有办法让我掌握我应该使用的操作系统相关的(我认为它是操作系统相关的??)密码回显字符?

坦白说没有抓住你在这里说的话。您可以通过向

PasswordField.textPrperty()
添加更改侦听器来跟踪文本更改,并执行动画、计时器等。您可以通过扩展
PasswordFieldSkin
并通过 CSS
-fx-skin
使用它来覆盖默认的子弹遮罩。请参阅此处来源中的项目符号定义

public class PasswordFieldSkin extends TextFieldSkin {
    public static final char BULLET = '\u2022';

    public PasswordFieldSkin(PasswordField passwordField) {
        super(passwordField, new PasswordFieldBehavior(passwordField));
    }

    @Override protected String maskText(String txt) {
        TextField textField = getSkinnable();

        int n = textField.getLength();
        StringBuilder passwordBuilder = new StringBuilder(n);
        for (int i=0; i<n; i++) {
            passwordBuilder.append(BULLET);
        }

        return passwordBuilder.toString();
    }
}

最后,这是使用绑定显示密码字符的演示应用程序:

@Override
public void start(Stage primaryStage) {

    // text field to show password as unmasked
    final TextField textField = new TextField();
    // Set initial state
    textField.setManaged(false);
    textField.setVisible(false);

    // Actual password field
    final PasswordField passwordField = new PasswordField();

    CheckBox checkBox = new CheckBox("Show/Hide password");

    // Bind properties. Toggle textField and passwordField
    // visibility and managability properties mutually when checkbox's state is changed.
    // Because we want to display only one component (textField or passwordField)
    // on the scene at a time.
    textField.managedProperty().bind(checkBox.selectedProperty());
    textField.visibleProperty().bind(checkBox.selectedProperty());

    passwordField.managedProperty().bind(checkBox.selectedProperty().not());
    passwordField.visibleProperty().bind(checkBox.selectedProperty().not());

    // Bind the textField and passwordField text values bidirectionally.
    textField.textProperty().bindBidirectional(passwordField.textProperty());

    VBox root = new VBox(10);
    root.getChildren().addAll(passwordField, textField, checkBox);
    Scene scene = new Scene(root, 300, 250);
    primaryStage.setTitle("Demo");
    primaryStage.setScene(scene);
    primaryStage.show();
}

7
投票

您需要创建三个元素:

  • TextField :密码可见字段
  • PasswodField :密码不可见字段
  • CheckBox:切换可见性字段

将密码字段放置在相同位置(x,y):

<PasswordField fx:id="pass_hidden" layoutX="X" layoutY="Y" />
<TextField fx:id="pass_text" layoutX="X" layoutY="Y"/>
<CheckBox fx:id="pass_toggle" onAction="#togglevisiblePassword" .... />

注意: 替换

X
Y
的值。

添加您的控制器:

@FXML
private PasswordField pass_hidden;
@FXML
private TextField pass_text;
@FXML
private CheckBox pass_toggle;

/**
 * Controls the visibility of the Password field
 * @param event
 */
@FXML
public void togglevisiblePassword(ActionEvent event) {
    if (pass_toggle.isSelected()) {
        pass_text.setText(pass_hidden.getText());
        pass_text.setVisible(true);
        pass_hidden.setVisible(false);
        return;
    }
    pass_hidden.setText(pass_text.getText());
    pass_hidden.setVisible(true);
    pass_text.setVisible(false);
}

// The controller class needs to implement Initializable to override initialize
@Override
public void initialize(URL location, ResourceBundle resources) {
    this.togglevisiblePassword(null);
}

如果您想知道密码的值,您可以创建一个返回它的方法:

private String passwordValue() {
    return pass_toggle.isSelected()?
       pass_text.getText(): pass_hidden.getText();
}

3
投票

我知道这很旧,但我正在寻找答案,这是我的解决方案:

@FXML
private JFXButton showpassword;
private String password;

showpassword.addEventFilter(MouseEvent.MOUSE_PRESSED, e -> {
            password = passwordField.getText();
            passwordField.clear();
            passwordField.setPromptText(password);
        });
        showpassword.addEventFilter(MouseEvent.MOUSE_RELEASED, e -> {
            passwordField.setText(password);
            passwordField.setPromptText("Password");
        });

使用“WIN10 Eye - 解锁密码”等图形按钮


2
投票

您可以使用自定义

Tooltip
显示密码,并使用
Checkbox
显示/隐藏
Tooltip

此演示的代码可以在这里找到。


2
投票

好吧,密码字段有一个属性可以设置项目符号中的文本。此方法 maskText(String txt) 保留在皮肤上。您可以用新的皮肤替换它。当您键入方法 maskText 测试时,如果您可以替换为项目符号.. 使用一个布尔值来通知.. 您可以从另一事件重用此代码。这是一个例子。问候

public class Main extends Application {

@Override
public void start(Stage stage) throws Exception {
    StackPane root = new StackPane();
    root.setAlignment(Pos.CENTER);
    root.setPadding(new Insets(50));

    PasswordField passwordField = new PasswordField();
    passwordField.setSkin(new VisiblePasswordFieldSkin(passwordField));

    root.getChildren().add(passwordField);

    stage.setScene(new Scene(root, 400, 400));
    stage.show();
}


}

class VisiblePasswordFieldSkin extends TextFieldSkin {

private final Button actionButton = new Button("View");
private final SVGPath actionIcon = new SVGPath();

private boolean mask = true;

public VisiblePasswordFieldSkin(PasswordField textField) {

    super(textField);

    actionButton.setId("actionButton");
    actionButton.setContentDisplay(ContentDisplay.GRAPHIC_ONLY);
    actionButton.setPrefSize(30,30);
    actionButton.setFocusTraversable(false);
    actionButton.setBackground(new Background(new BackgroundFill(Color.TRANSPARENT, CornerRadii.EMPTY, new Insets(0))));

    getChildren().add(actionButton);
    actionButton.setCursor(Cursor.HAND);
    actionButton.toFront();

    actionIcon.setContent(Icons.VIEWER.getContent());
    actionButton.setGraphic(actionIcon);

    actionButton.setVisible(false);
    
    actionButton.setOnMouseClicked(event -> {

        if(mask) {
            actionIcon.setContent(Icons.VIEWER_OFF.getContent());
            mask = false;
        } else {
            actionIcon.setContent(Icons.VIEWER.getContent());
            mask = true;
        }
        textField.setText(textField.getText());

        textField.end();

    });

    textField.textProperty().addListener((observable, oldValue, newValue) -> actionButton.setVisible(!newValue.isEmpty()));

}

@Override
protected void layoutChildren(double x, double y, double w, double h) {
    super.layoutChildren(x, y, w, h);

    layoutInArea(actionButton, x, y, w, h,0, HPos.RIGHT, VPos.CENTER);
}

@Override
protected String maskText(String txt) {
    if (getSkinnable() instanceof PasswordField && mask) {
        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;
    }
}
}

enum Icons {

VIEWER_OFF("M12 6c3.79 0 7.17 2.13 8.82 5.5-.59 1.22-1.42 2.27-2." +
        "41 3.12l1.41 1.41c1.39-1.23 2.49-2.77 3.18-4.53C21.27 7.11 17 4 12 4c-1.27 " +
        "0-2.49.2-3.64.57l1.65 1.65C10.66 6.09 11.32 6 12 6zm-1.07 1.14L13 9.21c.57.25 1.03.71 " +
        "1.28 1.28l2.07 2.07c.08-.34.14-.7.14-1.07C16.5 9.01 14.48 7 12 7c-.37 0-.72.05-1.07." +
        "14zM2.01 3.87l2.68 2.68C3.06 7.83 1.77 9.53 1 11.5 2.73 15.89 7 19 12 19c1.52 0 2.98-.29 " +
        "4.32-.82l3.42 3.42 1.41-1.41L3.42 2.45 2.01 3.87zm7.5 7.5l2.61 2.61c-.04.01-.08.02-.12.02-1.38 " +
        "0-2.5-1.12-2.5-2.5 0-.05.01-.08.01-.13zm-3.4-3.4l1.75 1.75c-.23.55-.36 1.15-.36 1.78 0 2.48 2.02 " +
        "4.5 4.5 4.5.63 0 1.23-.13 1.77-.36l.98.98c-.88.24-1.8.38-2.75.38-3.79 0-7.17-2.13-8.82-5.5.7-1.43 1.72-2.61 2.93-3.53z"),

VIEWER("M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7." +
        "5-11-7.5zM12 17c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z");

private String content;

Icons(String content) {
    this.content = content;
}

public String getContent() {
    return content;
}
}

在GitHub查看


0
投票
 void viewpass(ActionEvent event) {




  if (checkpass.isSelected()){
 pass.setPromptText(pass.getText());
 pass.setText(""); 
  pass.setDisable(true);

  }else {
 pass .setText(pass.getPromptText());
 pass.setPromptText("");
 pass.setDisable(false);
 }






}

0
投票

您还可以使用带有单选按钮的文本字段和密码字段来完成此操作,如下所示。

import javafx.fxml.Initializable;
import com.jfoenix.controls.*;
import com.jfoenix.controls.JFXPasswordField;
import com.jfoenix.controls.JFXRadioButton;
import javafx.fxml.FXML;
import java.net.URL;
import java.util.ResourceBundle;

public class Controller implements Initializable{
    @FXML
    private JFXPasswordField PasswordField;
    @FXML
    private JFXRadioButton passVisible;
    @FXML
    private JFXTextField textField1;
    @Override
    public void initialize(URL location, ResourceBundle resources)
    {
textField1.textProperty().bind(PasswordField.textProperty());
textField1.visibleProperty().bind(passVisible.selectedProperty());
PasswordField.visibleProperty().bind(passVisible.selectedProperty().not());
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.