您可以使用DocumentFilter
允许您实时过滤来自用户的传入结果的 API。
这个例子有点棘手,因为它隐藏了插入符号,以便它允许文本以您想要的任何顺序出现。
例如,该示例Duck
用作机密(算法不区分大小写)。如果用户键入c,则该字段将显示为__c_
。当然,您可以简单地将传入的角色插入到下一个位置,但其中的乐趣在哪里。

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagLayout;
import java.awt.Point;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.ChangeListener;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Caret;
import javax.swing.text.DefaultCaret;
import javax.swing.text.DocumentFilter;
import javax.swing.text.JTextComponent;
public class HangManField {
public static void main(String[] args) {
new HangManField();
}
public HangManField() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class TestPane extends JPanel {
private String secret = "Duck";
private String guesses = secret;
public TestPane() {
setLayout(new GridBagLayout());
Caret blank = new DefaultCaret() {
@Override
public void paint(Graphics g) {
}
@Override
public boolean isVisible() {
return false;
}
@Override
public boolean isSelectionVisible() {
return false;
}
};
JTextField field = new JTextField("____");
field.setCaretPosition(0);
field.setCaret(blank);
((AbstractDocument) field.getDocument()).setDocumentFilter(new DocumentFilter() {
@Override
public void insertString(DocumentFilter.FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException {
replace(fb, offset, offset, string, attr);
}
@Override
public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException {
System.out.println("rplace");
StringBuilder sb = new StringBuilder(guesses.toLowerCase());
for (int index = 0; index < text.length(); index++) {
String at = text.substring(index, index + 1).toLowerCase();
int subIndex = sb.indexOf(at);
if (subIndex > -1) {
super.replace(fb, subIndex, 1, at, attrs);
sb.delete(index, index);
}
}
}
@Override
public void remove(DocumentFilter.FilterBypass fb, int offset, int length) throws BadLocationException {
StringBuilder sb = new StringBuilder(length);
while (sb.length() < length) {
sb.append("_");
}
replace(fb, offset, length, sb.toString(), null);
}
});
add(field);
}
}
}
该算法不做的事情是当前支持多个重复字符,例如characters
. 不过,完成这项工作并不需要太多时间;)