16

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

带有 JavaFX PasswordField 的登录对话框

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

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

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

4

7 回答 7

40

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

默认情况下,PasswordField组件不显示蒙版文本。但是,您可以分别使用这些组件来PasswordField使用TextField和切换蒙版/未蒙版文本。未屏蔽的文本由 显示TextField,如下面的示例演示所示。

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

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

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

坦率地说,没有抓住你在这里说的话。您可以通过添加更改侦听器并执行动画、计时器等来跟踪文本更改。您可以通过扩展和使用 CSSPasswordField.textPrperty()来覆盖默认的项目符号掩码。请在此处查看其源代码中的子弹定义:PasswordFieldSkin-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();
}
于 2013-06-09T21:50:39.090 回答
5

您需要创建三个元素:

  • 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" .... />

注意:替换 和 的XY

添加你的控制器:

@FXML
private TextField pass_text;
@FXML
private CheckBox pass_toggle;
@FXML
private Button btn_start_stop;

/**
 * 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);
}

//Run
@Override
public void initialize(URL location, ResourceBundle resources) {
    this.togglevisiblePassword(null);
}

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

private String passwordValue() {
    return pass_toggle.isSelected()?
       pass_text.getText(): pass_hidden.getText();
}
于 2017-07-21T22:04:32.927 回答
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 - 取消屏蔽密码”

于 2018-11-20T15:03:03.863 回答
1

您可以使用自定义Tooltip来显示密码,并使用Checkbox来显示/隐藏 Tooltip.

在此处输入图像描述

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

于 2020-02-04T16:16:40.150 回答
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);
 }






}
于 2018-08-22T20:26:40.097 回答
0

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

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 中查看

于 2021-11-23T16:06:40.957 回答
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());
    }
}
于 2021-07-06T10:38:57.997 回答