Fill a JPasswordField programmatically without creating a String object

一笑奈何 提交于 2019-12-23 02:04:30

问题


Is there a simple way to fill the document of a JPasswordField without creating a String object that contains the password?

I was trying to create a "change password" dialog which takes in the old password and requires the new one to be entered twice (three password fields), where the old password may be known before hand, depending on how the user configured this (password may have been stored). So instead of requiring the user to enter the existing password each time the associated dialog is shown to her, I wanted to fill it out programmatically.

Note that JPasswordField.setText(String) and the String constructor are not an option. I'd like to do this using a char array.

I've been trying to abuse GapContent which seems to be used by PlainDocument, but it doesn't seem to work (the chars are in there but the field is corrupted):

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JPasswordField;
import javax.swing.text.PlainDocument;
import javax.swing.SwingUtilities;
import javax.swing.text.GapContent;

public class FillJPasswordField extends JFrame {

    private JPasswordField pass;

    public FillJPasswordField() {
        setLayout(new GridBagLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        char[] password = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};
        PlainDocument doc = new PlainDocument(new MyGapContent(password));

        pass = new JPasswordField(doc, null, 20);

        // see if the password is in there
        System.out.println(new String(pass.getPassword()));

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.weightx = 1.0d;
        gbc.insets = new Insets(10, 5, 10, 5);

        add(pass, gbc);

        pack();
        setLocationRelativeTo(null);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                new FillJPasswordField().setVisible(true);
            }
        });
    }

    private class MyGapContent extends GapContent {

        public MyGapContent() {
            super();
        }

        public MyGapContent(int initialLength) {
            super(initialLength);
        }

        public MyGapContent(char[] content) {
            this(content.length);
            replace(0, 0, content, content.length);
        }

    }
}

回答1:


Hmm.. The following seems to work:

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import javax.swing.JFrame;
import javax.swing.JPasswordField;
import javax.swing.SwingUtilities;
import javax.swing.text.BadLocationException;
import javax.swing.text.GapContent;
import javax.swing.text.PlainDocument;

public class FillJPasswordField extends JFrame {

    private JPasswordField pass;

    public FillJPasswordField() {
        setLayout(new GridBagLayout());
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        char[] password = new char[]{'p', 'a', 's', 's', 'w', 'o', 'r', 'd'};

        MyGapContent content = new MyGapContent();
        PlainDocument doc = new PlainDocument(content);
        try {
            content.insertChars(0, password);
        } catch (BadLocationException ex) {
        }
        pass = new JPasswordField(20);
        pass.setDocument(doc);

        GridBagConstraints gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.anchor = GridBagConstraints.PAGE_START;
        gbc.weightx = 1.0d;
        gbc.insets = new Insets(10, 5, 10, 5);
        add(pass, gbc);

        System.out.println(new String(pass.getPassword()));

        pack();
        setLocationRelativeTo(null);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                new FillJPasswordField().setVisible(true);
            }
        });
    }

    private class MyGapContent extends GapContent {

        public MyGapContent() {
            super();
        }

        public MyGapContent(int initialLength) {
            super(initialLength);
        }

        public void insertChars(int where, char[] chars) throws BadLocationException {
            if (where > length() || where < 0) {
                throw new BadLocationException("Invalid insert", length());
            }
            replace(where, 0, chars, chars.length);
        }
    }
}

Previous code didn't seem to like the fact that I was calling replace inside the constructor of MyGapContent. Perhaps it requires operations to be done in some sequence.



来源:https://stackoverflow.com/questions/26975275/fill-a-jpasswordfield-programmatically-without-creating-a-string-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!