背景
JavaFx密碼框控件,最近碰到了“兼容性”問題,密碼框控件在大部分機器運行正常,但是客戶還有一部分用的是XP系統,在其電腦上出現了密碼框中黑色圓點不顯示的問題。
過程
解決這個問題的方案就是想辦法將黑色圓點修改爲其他可顯示的字符,我想到了兩種方式;
- 不使用PasswordField,用其他控件(如TextField)來實現密碼框的功能
- 修改PasswordField,看能否修改其回顯的字符
這裏我是使用的是第二種方案,第一種方式我在網上找到代碼,並沒有實踐,不知是否可行利用JavaFx開發RIA桌面應用-TextField替換PasswordField做密碼框。
通過對PasswordField的方法進行查看,我發現沒有直接修改回顯字符的方法,所以我看了源代碼,最終發現設置回顯字符使用的是 TextFieldSkin.java 類,代碼如下:
...
/**
* Text field skin.
*/
public class TextFieldSkin extends TextInputControlSkin<TextField, TextFieldBehavior> {
...
// For use with PasswordField
public static final char BULLET = '\u25cf';/* 這裏就是圓點了 */
/**
* Create a new TextFieldSkin.
* @param textField not null
*/
public TextFieldSkin(final TextField textField) {
this(textField, (textField instanceof PasswordField)
? new PasswordFieldBehavior((PasswordField)textField)
: new TextFieldBehavior(textField));
}
...
/* 通過這裏來設置回顯 */
@Override protected String maskText(String txt) {
if (getSkinnable() instanceof PasswordField) {
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;
}
}
}
那麼接下來的問題就是
- 如何修改這個回顯字符
- 如何將修改應用到PasswordField中
由於源代碼中的回顯字符是一個常量,並不允許修改,所以這裏只能夠自己寫一個類,繼承 TextFieldSkin.java 類 ,並重寫maskText方法,將回顯字符換成我們想要的字符即可,代碼如下:
package com.rratchet.strategy.control.skin;
import com.sun.javafx.scene.control.behavior.TextFieldBehavior;
import com.sun.javafx.scene.control.skin.TextFieldSkin;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
/**
* @author zgb
* @date 2019/12/5 14:53
* @description 解決xp“兼容性”問題,密碼框中黑色圓點無法顯示
*/
public class MyTextFiledSkin extends TextFieldSkin {
/**
* 回顯字符,可設置成自己想要的字符
*/
private char BULLET = '\u25cf';
public MyTextFiledSkin(TextField textField, char bullet) {
super(textField);
this.BULLET = bullet;
}
public MyTextFiledSkin(TextField textField) {
super(textField);
}
public MyTextFiledSkin(TextField textField, TextFieldBehavior behavior) {
super(textField, behavior);
}
@Override
protected String maskText(String txt) {
if (getSkinnable() instanceof PasswordField) {
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;
}
}
public char getBULLET() {
return BULLET;
}
public void setBULLET(char BULLET) {
this.BULLET = BULLET;
}
}
第一個問題解決了,接下來就是第二個問題,如何將修改應用到PasswordField中,通過對PasswordField的方法進行查看,我發現可通過setSkin方法將修改應用到PasswordField中,代碼如下:
PasswordField passwordTxt = new PasswordField();
TextFieldSkin textFieldSkin = new MyTextFiledSkin(passwordTxt,'#');
passwordTxt.setSkin(textFieldSkin);
完成!效果如下: