问题
I am trying to find the method that actually renders the JPassword field. Maybe render is not the right word, so here is the deal:
I am trying to make the JPassword field show a different number of characters instead of the same length as the actual password i am typing. For example, if i type 123456 for the password and setEchoChar((Character)value) to "#"
The password would show like this: # # # # # #
I want to be able to generate a random number of stars to show: # # # # # # # # # #
if the number was 10 for example. (Without the spaces of course)
I was able to do it by just adding a couple of listeners to detect changes then take the text and replace it with a mask that i create, but thats not satisfying, I want to be able to change the behavior of the actual object. A little challenge won't hurt, right? :) I am ready for any suggestions. Thank you.
回答1:
I think I found a way to "right" solution although I did not manage to implement it now. Here are the tips:
the echo character is drown by PasswordView.drawEchoCharacter(). This is protected method. It can be overridden, so you can draw as many characters as you want. The instance of PasswordView is created by BasicPassworFieldUI.create(Element). Instance of BasicPassworFieldUI is assigned by JComponent.setUI().
So, the way I'd suggest is:
- Implement MyPasswordView extends PasswordView and overrides drawEchoCharacter()
- Implement MyPasswordUI extends BasicPasswordFieldUI that overrides View create(Element elem) and creates instance of MyPasswordView.
- Override setUI() of JPasswordField and set their MyPasswordUI.
I implemented all this but it still does not work although my methods are called. I believe that the bug is in return value of my drawEchoCharacter(). It is 2AM now and I will not fix the bug but I believe you can.
I wish you good luck and will be happy to know that you succeeded to fix this.
Here is my code:
public class TestPassword {
public static void main(String[] args) {
JFrame f = new JFrame();
JPasswordField p = new JPasswordField() {
public void setUI(TextUI ui) {
super.setUI(new MyPasswordUI());
}
};
//p.setUI(ui)
//p.setEchoChar('q');
final Random r = new Random();
f.add(p);
f.setSize(100, 100);
f.setLocation(100, 100);
f.setVisible(true);
}
public static class MyPasswordUI extends BasicPasswordFieldUI {
public View create(Element elem) {
return new MyPasswordView(elem);
}
}
public static class MyPasswordView extends PasswordView {
public MyPasswordView(Element elem) {
super(elem);
}
protected int drawEchoCharacter(Graphics g, int x, int y, char c) {
super.drawEchoCharacter(g, x, y, c);
return super.drawEchoCharacter(g, x, y, c);
}
}
}
回答2:
I'm not really sure about this, but maybe a custom Highlighter can accomplish this?
passwordField.setHighlighter(new MySpecialPasswordHighlighter());
来源:https://stackoverflow.com/questions/4810777/rendering-java-jpasswordfield