web-dev-qa-db-fra.com

JOptionPane pour obtenir le mot de passe

JOptionPane peut être utilisé pour obtenir les entrées de chaîne de l'utilisateur, mais dans mon cas, je souhaite afficher un champ de mot de passe dans showInputDialog.

La façon dont j'ai besoin est que l'entrée donnée par l'utilisateur doit être masquée et que la valeur de retour doit être en char[]. J'ai besoin d'une boîte de dialogue avec un message, un champ de mot de passe et deux boutons. Cela peut-il être fait? Merci.

44
Ahamed

Oui, il est possible d’utiliser JOptionPane.showOptionDialog() . Quelque chose comme ça:

JPanel panel = new JPanel();
JLabel label = new JLabel("Enter a password:");
JPasswordField pass = new JPasswordField(10);
panel.add(label);
panel.add(pass);
String[] options = new String[]{"OK", "Cancel"};
int option = JOptionPane.showOptionDialog(null, panel, "The title",
                         JOptionPane.NO_OPTION, JOptionPane.PLAIN_MESSAGE,
                         null, options, options[1]);
if(option == 0) // pressing OK button
{
    char[] password = pass.getPassword();
    System.out.println("Your password is: " + new String(password));
}
61
Eng.Fouad

Le plus simple est d’utiliser la méthode JOptionPane's showConfirmDialog et de faire référence à une JPasswordField; par exemple.

JPasswordField pf = new JPasswordField();
int okCxl = JOptionPane.showConfirmDialog(null, pf, "Enter Password", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);

if (okCxl == JOptionPane.OK_OPTION) {
  String password = new String(pf.getPassword());
  System.err.println("You entered: " + password);
}

Modifier

Vous trouverez ci-dessous un exemple d'utilisation d'une variable JPanel personnalisée pour afficher un message avec la variable JPasswordField. Selon le commentaire le plus récent, j'ai également ajouté (à la hâte) du code permettant au JPasswordField de se concentrer lorsque la boîte de dialogue est affichée pour la première fois.

public class PasswordPanel extends JPanel {
  private final JPasswordField passwordField = new JPasswordField(12);
  private boolean gainedFocusBefore;

  /**
   * "Hook" method that causes the JPasswordField to request focus the first time this method is called.
   */
  void gainedFocus() {
    if (!gainedFocusBefore) {
      gainedFocusBefore = true;
      passwordField.requestFocusInWindow();
    }
  }

  public PasswordPanel() {
    super(new FlowLayout());

    add(new JLabel("Password: "));
    add(passwordField);
  }

  public char[] getPassword() {
      return passwordField.getPassword();
  }

  public static void main(String[] args) {
      PasswordPanel pPnl = new PasswordPanel();
      JOptionPane op = new JOptionPane(pPnl, JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);

      JDialog dlg = op.createDialog("Who Goes There?");

      // Wire up FocusListener to ensure JPasswordField is able to request focus when the dialog is first shown.
      dlg.addWindowFocusListener(new WindowAdapter() {
        @Override
        public void windowGainedFocus(WindowEvent e) {
            pPnl.gainedFocus();
        }
      });

      if (op.getValue() != null && op.getValue().equals(JOptionPane.OK_OPTION)) {
          String password = new String(pPnl.getPassword());
          System.err.println("You entered: " + password);
      }
  }
}
36
Adamski

Vous pouvez créer votre propre dialogue qui étend JDialog, puis vous pouvez y placer ce que vous voulez.

4
OnResolve

Ce dialogue est beaucoup mieux si vous le faites

dlg.setVisible(true);

Sans cela, vous ne pouvez pas le voir du tout.

Également

pPnl.gainedFocus();

devrait être

pPnl.gainedFocus();

Autre que cela fonctionne très bien. Merci pour le code. M'a fait gagner du temps en faisant face à Swing.

De plus, si vous ne voulez pas laisser le dialogue en arrière-plan chaque fois que vous l'ouvrez, vous devrez le fermer avec quelque chose comme:

dlg.dispatchEvent(new WindowEvent(dlg, WindowEvent.WINDOW_CLOSING));
dlg.dispose(); // else Java VM will wait for dialog to be disposed of (forever)
3
Peter West

La classe suivante est une extension de La grande réponse d'Adamski :

package com.stackoverflow.swing;

import Java.awt.Component;
import Java.awt.Dimension;
import Java.awt.FlowLayout;
import Java.awt.event.WindowAdapter;
import Java.awt.event.WindowEvent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;

/**
 * Class that creates a panel with a password field. Extension of Adamski's class
 *
 * @author adamski https://stackoverflow.com/users/127479/adamski
 * @author agi-hammerthief https://stackoverflow.com/users/2225787/agi-hammerthief
 * @see https://stackoverflow.com/a/8881370/2225787
 */
public class PasswordPanel extends JPanel {

  private final JPasswordField JFieldPass;
  private JLabel JLblPass;
  private boolean gainedFocusBefore;

  /**
   * "Hook" method that causes the JPasswordField to request focus when method is
   * first  called.
   */
  public void gainedFocus () {
    if (!gainedFocusBefore) {
      gainedFocusBefore = true;
      JFieldPass.requestFocusInWindow();
    }
  }

  public PasswordPanel (int length) {
    super(new FlowLayout());
    gainedFocusBefore = false;
    JFieldPass = new JPasswordField(length);
    Dimension d = new Dimension();
    d.setSize(30, 22);
    JFieldPass.setMinimumSize(d);
    JFieldPass.setColumns(10);
    JLblPass = new JLabel("Password: ");
    add(JLblPass);
    add(JFieldPass);
  }

  public PasswordPanel() {
    super(new FlowLayout());
    gainedFocusBefore = false;
    JFieldPass = new JPasswordField();
    Dimension d = new Dimension();
    d.setSize(30, 22);
    JFieldPass.setMinimumSize(d);
    JFieldPass.setColumns(10);
    JLblPass = new JLabel("Password: ");
    add(JLblPass);
    add(JFieldPass);
  }

  public char[] getPassword() {
    return JFieldPass.getPassword();
  }

  public String getPasswordString() {
    StringBuilder passBuilder = new StringBuilder();

    char[] pwd = this.getPassword();
    if (pwd.length > 0) {
      for (char c : pwd) {
        passBuilder.append(c);
      }
    }

    return passBuilder.toString();
  }

  private static String displayDialog (
    Component parent, final PasswordPanel panel, String title
  ) {
    String password = null;
    /* For some reason, using `JOptionPane(panel, JOptionPane.OK_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE)`
    does not give the same results as setting values after creation, which is weird */
    JOptionPane op = new JOptionPane(panel);
    op.setMessageType(JOptionPane.QUESTION_MESSAGE);
    op.setOptionType(JOptionPane.OK_CANCEL_OPTION);
    JDialog dlg = op.createDialog(parent, title);
    // Ensure the JPasswordField is able to request focus when the dialog is first shown.
    dlg.addWindowFocusListener (new WindowAdapter () {
      @Override
      public void windowGainedFocus (WindowEvent e) {
        panel.gainedFocus ();
      }
    });
    dlg.setDefaultCloseOperation (JOptionPane.OK_OPTION); // necessary?

    dlg.setVisible (true);

    Object val = op.getValue ();
    if (null != val && val.equals (JOptionPane.OK_OPTION)) {
      password = panel.getPasswordString();
    }

    return password;
  }

  public static String showDialog (Component parent, String title) {
    final PasswordPanel pPnl = new PasswordPanel();
    return displayDialog(parent, pPnl, title);
  }

  public static String showDialog (
    Component parent, String title, int passwordLength
  ) {
    final PasswordPanel pPnl = new PasswordPanel(passwordLength);

    return displayDialog (parent, pPnl, title);
  }

  public static String showDialog (String title) {
    return showDialog(null, title);
  }

  public static String showDialog (String title, int passwordLength) {
    return showDialog(null, title, passwordLength);
  }

  /**
   * Show a test dialog
   */
  public static void main(String[] args) {
    String test = PasswordPanel.showDialog ("Enter Your Password");
    System.out.println ("Entered Password: " + test);
    System.exit(0);
  }

}
0
Agi Hammerthief