Wie lässt sich ein Passwortfeld realisieren?
Ein
stellt, wie
seine Elternklasse, ein einzeiliges Feld zur Aufnahme
von Text dar, weist demgegenüber jedoch einige
Besonderheiten auf:
JPasswordField
- Der Eingabe-String wird nicht als Klartext gezeigt, sondern durch Punkte maskiert.
- Er kann nicht durch eine Tastatureingabe in die Zwischenablage kopiert werden.
- Die von
JTextField
geerbte Methode zur Rückgabe des Eingabe-StringsgetText()
ist als deprecated markiert und wird durchgetPassword()
ersetzt. Sie liefert statt eines Strings ein char-Array.
Die Konstruktoren des JPasswordField
sind
fünffach überladen und entsprechen denen von
JTextField. Ihnen können in unterschiedlichen
Kombinationen Argumente für die Spaltenzahl, den
eingegebenen Text und den Dokumenttyp der Eingabe
übergeben werden.
Echo-Character ändern
Als Echo-Character werden die Platzhalterzeichen
benannt, die die Klartextzeichen im Eingabefeld ersetzen
und so ein unberechtigtes Auslesen verhindern sollen. JPasswordField
verwendet als Standard einen Punkt '●', den
Unicode-Character \u25cf
, der dem
Integer-Literal 9679 entspricht. Er kann durch die
Methode setEchoChar​(char c)
wie im
folgenden Beispiel gezeigt geändert werden:
public class PasswortFeldBsp { public static void main(String[] args) { SwingUtilities.invokeLater(() -> new PasswortFeldBsp().initGUI()); } private void initGUI() { JPanel panel = new JPanel(new BorderLayout()); JPasswordField pf = new JPasswordField(10); pf.setEchoChar('\u25ce'); panel.add(pf, BorderLayout.CENTER); JFrame frame = new JFrame(); frame.add(panel); frame.setTitle("Passwort-Feld"); frame.pack(); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } }
Einem JFrame
wird hier ein JPanel
hinzugefügt, auf das zentrisch ein zehnspaltiges JPasswordField
gesetzt ist. Der Ausdruck setEchoChar('\u25ce');
ändert den Echo-Character des Feldes auf das
Zeichen \u25ce
.
Wechsel der Anzeige
Möchte man eine Passworteingabe realisieren, die zwischen der maskierten Anzeige und dem Klartext wechselt, so kann die o.a. Methode verwendet werden. Als Echo-Character muss zur Anzeige des Klartextes dann '0' zugewiesen werden. Die folgende Methode wechselt zwischen beiden Darstellungsoptionen und kann etwa durch einen Button aufgerufen werden.
private void toggleView(JPasswordField field) { char c = field.getEchoChar(); c = c == 0 ? (char) 9679 : (char) 0; field.setEchoChar(c); }
Passwort kopieren
Das Kopieren eines Passworts durch Markieren und z.B.
Eingabe von <Cmd>+<c> ist bei einem JPasswordField
nicht möglich. Ein Kopieren in die Zwischenablage
kann jedoch programmatisch erfolgen.
private void copyToClip(char[] c) { Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard(); StringSelection sel; String pass = new String(c); if (pass.length() > 0) { sel = new StringSelection(pass); } else { return; } clip.setContents(sel, null); }
Das Beispiel zeigt eine vereinfachte Form der
Übernahme des Passworts in die Zwischenablage.
Für eine ausführlichere Diskussion der
Zwischenablage sei auf den entsprechenden
Artikel im Abschnitt Systemzugriff
verwiesen.
Im Beispiel wird zunächst ein Clipboard
-Objekt
erzeugt, das die Funktionalität der
System-Zwischenablage repräsentiert. Der Inhalt
kann ihr nur als StringSelection
übergeben werden. Das Objekt implementiert die
Schnittstelle Transferable
und speichert
die Metadaten des zu übertragenden Inhalts.
Der folgende Quelltext fasst das bislang Gezeigte
zusammen und erzeugt einen kleinen JFrame
mit JPasswordField
und zwei Buttons. Der
rechte steuert den Wechsel des Echo-Characters, der
linke veranlasst das Kopieren der Eingabe in die
Zwischenablage.
public class PasswortFeld { public static void main(String[] args) { SwingUtilities.invokeLater(() -> new PasswortFeld().initGUI()); } private void initGUI() { JPanel panel = new JPanel(new BorderLayout()); ImageIcon copyIcon = null, changeIcon = null; try { copyIcon = new ImageIcon(ImageIO.read(getClass().getResource("/img/copy.png"))); changeIcon = new ImageIcon(ImageIO.read(getClass().getResource("/img/refresh.png"))); } catch (IOException e1) { e1.printStackTrace(); } JPasswordField pf = new JPasswordField(10); JButton changeButt = new JButton(changeIcon); changeButt.addActionListener(e -> toggleView(pf)); JButton copyButt = new JButton(copyIcon); copyButt.addActionListener(e -> copyToClip(pf.getPassword())); panel.add(copyButt, BorderLayout.WEST); panel.add(pf, BorderLayout.CENTER); panel.add(changeButt, BorderLayout.EAST); JFrame frame = new JFrame(); frame.add(panel); frame.setTitle("Passwort-Feld"); frame.pack(); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } private void toggleView(JPasswordField field) { char c = field.getEchoChar(); c = c == 0 ? (char) 9679 : (char) 0; field.setEchoChar(c); } private void copyToClip(char[] c) { Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard(); StringSelection sel; String pass = new String(c); if (pass.length() > 0) { sel = new StringSelection(pass); } else { return; } clip.setContents(sel, null); } }
Alternativer Anzeigewechsel
Eine etwas 'holprigere' Variante zum Wechsel zwischen
Klartext und Maskierung der Eingabe besteht darin, das
Eingabefeld zu tauschen. Sie ermöglicht
gleichzeitig das Kopieren des Klartextes.
Das Prinzip
besteht darin, durch eine Buttonaktion das JPasswordField
gegen ein JTextField
zu tauschen und den
eingegebenen Text entsprechend zu setzen. Im folgenden
Beispiel wird die Methode toggleField()
durch einen Button aufgerufen. Sie wechselt zwischen
beiden Eingabefeldern, setzt deren Sichtbarkeit, sowie
die erfolgte Eingabe entsprechend und zeichnet
schließlich das UI neu. Ist die Eingabe als
Klartext sichtbar, kann sie durch Markieren und kopieren
per Tastatur in die Zwischenablage übernommen
werden, da die zugrunde liegende Komponente ein JTextField
ist.
public class PasswortFeld { public static void main(String[] args) { SwingUtilities.invokeLater(() -> new PasswortFeld().initGUI()); } private void initGUI() { JPanel panel = new JPanel(new BorderLayout()); ImageIcon changeIcon = null; try { changeIcon = new ImageIcon(ImageIO.read(getClass().getResource("/img/refresh.png"))); } catch (IOException e1) { e1.printStackTrace(); } JPasswordField pf = new JPasswordField(10); pf.setVisible(true); JTextField tf = new JTextField(10); tf.setVisible(false); JButton changeButt = new JButton(changeIcon); changeButt.addActionListener(e -> toggleField(panel, tf, pf)); panel.add(pf, BorderLayout.CENTER); panel.add(changeButt, BorderLayout.EAST); JFrame frame = new JFrame(); frame.add(panel); frame.setTitle("Passwort-Feld"); frame.pack(); frame.setLocationRelativeTo(null); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setVisible(true); } private void toggleField(JPanel panel, JTextField tf, PasswordField pf) { if (tf.isVisible()) { pf.setText(tf.getText()); tf.setVisible(false); panel.add(pf, BorderLayout.CENTER); pf.setVisible(true); } else { tf.setText(new String(pf.getPassword())); pf.setVisible(false); panel.add(tf, BorderLayout.CENTER); tf.setVisible(true); } panel.updateUI(); } }
Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.