Java 通过实现键绑定使用类型化键
您能帮助我如何使用Java 通过实现键绑定使用类型化键,java,swing,key-bindings,keylistener,Java,Swing,Key Bindings,Keylistener,您能帮助我如何使用KeyBinding和Consume一起输入Chars吗?方法与使用keylister演示我的SSCCE相同 import java.awt.*; import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import javax.swing.*; public class Login { private static final long serialVersionUID = 1L;
KeyBinding
和Consume
一起输入Chars
吗?方法与使用keylister
演示我的SSCCE
相同
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
public class Login {
private static final long serialVersionUID = 1L;
/* PassWord for unlock*/
private PswChecker checker = new PswChecker("pass");
public Login() {
JTextField firstField = new JTextField(10);
firstField.addKeyListener(passwordKeyListener);
JLabel firstLabel = new JLabel("Password is 'pass' ", JLabel.RIGHT);
firstLabel.setLabelFor(firstField);
JPanel p = new JPanel();
p.setLayout(new GridLayout(0, 2, 5, 5));
p.add(firstLabel);
p.add(firstField);
JFrame f = new JFrame("login");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setContentPane(p);
f.setLocationByPlatform(true);
f.pack();
f.setVisible(true);
}
//
private KeyListener passwordKeyListener = new KeyListener() {
private boolean enabled = true;
@Override
public void keyTyped(KeyEvent e) {
if (!enabled) {
return;
}
if (e.getKeyChar() != KeyEvent.CHAR_UNDEFINED) {
boolean b = checker.accept(e.getKeyChar());
e.consume();
if (b) {
enabled = false;
if (e.getComponent() != null) {
e.getComponent().removeKeyListener(this);
}
unlock();
}
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
}
};
void unlock() {
JOptionPane.showMessageDialog(null, "unlocked");
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
Login log = new Login();
}
});
}
class PswChecker {
private String password = null;
private boolean unlocked = false;
private long lastInputTimestamp = 0L;
private int index = 0;
public PswChecker(String password) {
if (password == null) {
throw new IllegalArgumentException("Null password");
}
if (password.trim().length() == 0) {
throw new IllegalArgumentException("Empty password");
}
this.password = password;
}
public boolean accept(char c) {
if (unlocked) {
return true;
}
long timestamp = System.currentTimeMillis();
if (timestamp - lastInputTimestamp > 700) {
index = 0;
}
lastInputTimestamp = timestamp;
if (password.charAt(index) == c) {
index++;
} else {
if (password.charAt(0) == c) {
index = 1;
} else {
index = 0;
}
}
unlocked = (index == password.length());
return unlocked;
}
public boolean isUnlocked() {
return unlocked;
}
public boolean isLocked() {
return !unlocked;
}
@Override
public String toString() {
return unlocked ? "UNLOCKED" : "LOCKED";
}
/*private boolean check(String keystrokes, String password, boolean expectUnLocked) {
PswChecker checker = new PswChecker(password);
for (int i = 0; i < keystrokes.length(); i++) {
checker.accept(keystrokes.charAt(i));
}
return checker.isUnlocked();
}*/
}
}
import java.awt.*;
导入java.awt.event.KeyEvent;
导入java.awt.event.KeyListener;
导入javax.swing.*;
公共类登录{
私有静态最终长serialVersionUID=1L;
/*解锁密码*/
私人PswChecker检查器=新PswChecker(“通过”);
公共登录(){
JTextField firstField=新的JTextField(10);
addKeyListener(passwordKeyListener);
JLabel firstLabel=newjlabel(“密码为‘pass’”,JLabel.RIGHT);
firstLabel.setLabelFor(firstField);
JPanel p=新的JPanel();
p、 setLayout(新的GridLayout(0,2,5,5));
p、 添加(第一个标签);
p、 添加(第一个字段);
JFrame f=新JFrame(“登录”);
f、 setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f、 setContentPane(p);
f、 setLocationByPlatform(真);
f、 包装();
f、 setVisible(真);
}
//
private KeyListener passwordKeyListener=new KeyListener(){
私有布尔启用=真;
@凌驾
public void keyTyped(KeyEvent e){
如果(!已启用){
返回;
}
if(e.getKeyChar()!=KeyEvent.CHAR\u未定义){
布尔b=checker.accept(例如getKeyChar());
e、 消费();
如果(b){
启用=错误;
如果(如getComponent()!=null){
e、 getComponent().removeKeyListener(此);
}
解锁();
}
}
}
@凌驾
公共无效密钥已释放(密钥事件e){
}
@凌驾
按下公共无效键(按键事件e){
}
};
无效解锁(){
showMessageDialog(null,“未锁定”);
}
公共静态void main(字符串[]args){
javax.swing.SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
登录日志=新登录();
}
});
}
类PswChecker{
私有字符串密码=null;
私有布尔值=false;
私有长lastInputTimestamp=0L;
私有整数指数=0;
公共PswChecker(字符串密码){
如果(密码==null){
抛出新的IllegalArgumentException(“空密码”);
}
if(password.trim().length()==0){
抛出新的IllegalArgumentException(“空密码”);
}
this.password=密码;
}
公共布尔接受(字符c){
如果(未锁定){
返回true;
}
长时间戳=System.currentTimeMillis();
如果(时间戳-lastInputTimestamp>700){
指数=0;
}
lastInputTimestamp=时间戳;
if(password.charAt(index)==c){
索引++;
}否则{
如果(密码字符(0)=c){
指数=1;
}否则{
指数=0;
}
}
解锁=(索引==密码.length());
返回解锁;
}
公共布尔值isUnlocked(){
返回解锁;
}
公共布尔值isLocked(){
返回!解锁;
}
@凌驾
公共字符串toString(){
返回未锁定?“未锁定”:“已锁定”;
}
/*私有布尔值检查(字符串击键、字符串密码、布尔值){
PswChecker checker=新的PswChecker(密码);
for(int i=0;i 安全性,考虑,说明。这将允许使用已讨论的
附录:即使对于更一般的情况,我也会使用a,如下所示。我将用于在组件之间共享操作
,如下所示
附录:为了说明@kleopatra的评论,我更新了将ESC绑定到Reset
的代码。实际上,我只会使用尚未绑定到文本字段操作或正常使用所需的键
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import javax.swing.*;
import javax.swing.text.*;
/** @see https://stackoverflow.com/q/9610386/230513 */
public class Login {
private static final String PWD = "pass";
private static final String RESET = "Reset";
private PlainDocument doc = new PlainDocument();
private JTextField text = new JTextField(doc, "", 10);
public Login() {
doc.setDocumentFilter(new FieldFilter(PWD));
JLabel label = new JLabel("Password is '" + PWD + "'", JLabel.RIGHT);
label.setLabelFor(text);
text.setToolTipText("Press ESC to reset.");
text.getInputMap().put(
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), RESET);
text.getActionMap().put(RESET, new Reset());
JPanel p = new JPanel();
p.setLayout(new GridLayout(0, 2, 5, 5));
p.add(label);
p.add(text);
JFrame f = new JFrame("Login");
f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
f.setContentPane(p);
f.setLocationByPlatform(true);
f.pack();
f.setVisible(true);
}
private static class FieldFilter extends DocumentFilter {
private String password;
private boolean unlocked;
private StringBuilder sb = new StringBuilder();
public FieldFilter(String password) {
this.password = password;
}
@Override
public void replace(FilterBypass fb, int offset, int length,
String text, AttributeSet attrs) throws BadLocationException {
if (unlocked) {
super.replace(fb, offset, length, text, attrs);
} else {
sb.append(text);
unlocked = password.equals(sb.toString());
}
}
public void reset() {
sb.delete(0, sb.length());
unlocked = false;
}
}
private static class Reset extends AbstractAction {
@Override
public void actionPerformed(ActionEvent e) {
JTextField jtf = (JTextField) e.getSource();
PlainDocument doc = (PlainDocument) jtf.getDocument();
try {
doc.remove(0, doc.getLength());
} catch (BadLocationException ex) {
ex.printStackTrace(System.err);
}
FieldFilter filter = (FieldFilter) doc.getDocumentFilter();
filter.reset();
}
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Login log = new Login();
}
});
}
}
+1这只是一个例子,还是你应该使用JPasswordField
?@trashgood对了,我的问题不是关于JPasswordField,而是关于使用KeyBindings中的事件,如果它不是密码,那它是什么?你到底想实现什么?对,这不是关于密码,1)
我不想使用(也许我知道如何使用)DocumentListener
或DocumentFilter
,2)想通过KeyBindings
监听JTextComponent
,并确定(在本例中,此逻辑转换为密码检查器)键入了一些字符,并覆盖事件。consume()
以输出到视图3)
现在我只能使用键侦听器进行事件。consume()
,whyyyyyyyyy?(对不起,我差点喊出声来,这15个字母的限制是…:)太好了,太好了,谢谢你(之前)投票支持+1,请向我道歉,我的目标是了解KeyBinding的工作原理:-(@mKorbel如果a)在搜索的任何InputMap中都可以找到绑定,b)绑定操作isEnabled@kleopatra这两种方法是键绑定的基本functionalites所必需的,您是在谈论将侦听器移动到第一个父级(JPanel或…)还是从操作将所需的事件仅分发到(在本例中,字符是从键盘输入的)JTextField还是我又错了,@mKorbel你指的是哪两种方法?不管怎样,没有你详细说明原因(在yo中)