您可以利用DocumentFilter
API 允许您实时过滤来自用户的传入结果。
这个示例有点棘手,因为它隐藏了插入符号,因此它允许文本以您想要的任何顺序显示。
For example, the example uses Duck
as the secret (the algorithm is case insensitive). If the user types c then the field will appear as __c_
. Of course, you could just simply insert the incoming character in the what ever position was next, but where's the fun in that.
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
。不过,你不需要花太多时间就能完成这项工作;)