我想实现这样一个功能:在一个文本框中按下a键,然后就会显示A,而不是a。
我是这样写的package model.component;import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;import javax.swing.JTextField;public class JKeyField extends JTextField{ private static final long serialVersionUID = 1L; public JKeyField(){
super();
this.addKeyListener(new KeyAdapter(){
public void keyTyped(KeyEvent e){
System.out.println("here");
JKeyField.this.setText("A");
}
});
}
}但当我调用时,输入a,它就会显示Aa,而不是a,请问这是什么原因?各位高手们有没有什么更好的方法。

解决方案 »

  1.   

    你说的这个功能要在模型层进行处理,给你贴个例子
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.text.*;
    import java.awt.event.*;import javax.swing.event.*;/**
     * 这个实例能够做到的是保证输入的字母全部为大写
     * 同时还可以做到复制文本
     * 
     * 这个实例是采用自己写Document的一个使用例子
     * @author ioegaoyong
     *
     */
    public class JTextFieldDemo extends JFrame{
    private JButton 
    b1=new JButton("输入文本"),
    b2=new JButton("拷贝");
    private JTextField
    t1=new JTextField(30),
    t2=new JTextField(30),
    t3=new JTextField(30);
    private String str=new String();

    //自定义了文本模型,继承自PlainDocument
    private UpperCaseDecument ucd=new UpperCaseDecument();

    public JTextFieldDemo(String title){
    super(title);
    b1.addActionListener(new ActionListenerB1());
    b2.addActionListener(new ActionListenerB2());

    t1.setDocument(ucd);

    //添加文档模型更改的监听器
    ucd.addDocumentListener(new DocumentListenerT());

    t1.addActionListener(new ActionListenerT());

    Container contentPane=this.getContentPane();
    contentPane.setLayout(new GridLayout(4,1));
    JPanel buttonPanel=new JPanel();
    buttonPanel.add(b1);
    buttonPanel.add(b2);
    contentPane.add(buttonPanel);
    contentPane.add(t1);
    contentPane.add(t2);
    contentPane.add(t3);

    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.pack();
    this.setLocationRelativeTo(null);
    this.setVisible(true);

    }
    /**
     * @param args
     */
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    new JTextFieldDemo("Hello");
    }

    class ActionListenerB1 implements ActionListener{
    public void actionPerformed(ActionEvent ae){
    t1.setEditable(true);
    }
    }
    class ActionListenerB2 implements ActionListener{
    public void actionPerformed(ActionEvent ae){
    if(t1.getSelectedText()==null){
    str=t1.getText();
    }else{
    str=t1.getSelectedText();
    }

    ucd.setUpperCase(false);
    t1.setText("Inserted by Button 2"+str);
    ucd.setUpperCase(true);
    t1.setEditable(false);
    }
    }

    class DocumentListenerT implements DocumentListener{ public void changedUpdate(DocumentEvent e) {
    // TODO Auto-generated method stub

    }

    //插入或更新
    public void insertUpdate(DocumentEvent e) {
    // TODO Auto-generated method stub
    t2.setText(t1.getText());
    t3.setText("Text: "+t1.getText());
    } public void removeUpdate(DocumentEvent e) {
    // TODO Auto-generated method stub
    t2.setText(t1.getText());
    }

    }
    class ActionListenerT implements ActionListener{
    private  int count=0;
    public void actionPerformed(ActionEvent e) {
    // TODO Auto-generated method stub
    t3.setText("t1 Action Event "+count++);

    }

    }}
    class UpperCaseDecument extends PlainDocument{
    //这里保证的是文本转化为大写,如果改成false,则可以大写或小写
    private boolean upperCase=true;

    public void setUpperCase(boolean flag){
    upperCase=flag;
    }
    public void insertString (int offset,String str,AttributeSet 
    attSet)throws BadLocationException{
    if(upperCase) str=str.toUpperCase();
    super.insertString(offset, str, attSet);
    }

    }
      

  2.   

    想法如下:
    JTextField组件的keyDown等事件,是由他的容器(比如form)先行截取处理,没有对应处理时,才传出去给JTextField组件。所以应在容器级别的事件(keyDown)上实现。
    1.判断当前输入控件是否是指定控件。
    2.当是指定控件,进行输入转换 A -> a。
      

  3.   

    使用 DocumentFilter
    import javax.swing.JFrame;
    import javax.swing.JTextField;
    import javax.swing.text.AttributeSet;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.DocumentFilter.FilterBypass;
    import javax.swing.text.DocumentFilter;
    import javax.swing.text.PlainDocument;public class Example {
        public static void main(final String[] args) {
            java.awt.EventQueue.invokeLater(new Runnable(){
                    public void run(){
                        JFrame frame = new JFrame("Example");                    PlainDocument document = new PlainDocument();
                        document.setDocumentFilter(new DocumentFilter(){
                                @Override public void insertString(DocumentFilter.FilterBypass fb,
                                                                   int offset,
                                                                   String s,
                                                                   AttributeSet as) throws BadLocationException {
                                    super.insertString(fb,offset,s.toUpperCase(),as);
                                }
                                @Override public void replace(DocumentFilter.FilterBypass fb,
                                                              int offset,
                                                              int length,
                                                              String s,
                                                              AttributeSet as) throws BadLocationException {
                                    super.replace(fb,offset,length,s.toUpperCase(),as);
                                }
                            });
                        JTextField input = new JTextField(document,"",10);
                        frame.add(input);
                        frame.pack();
                        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                        frame.setLocationRelativeTo(null);
                        frame.setVisible(true);
                    }
                });
        }
    }
      

  4.   

        你好,谢谢你的回复,刚刚我试了试你的方法果然好用,只不过我的原意是这样的:一个输入框,我现在按F1键就让显示“F1”,按回车键,显示“Enter”,按a显示“A”等等,这样的功能。
        我想的做法就是首先捕获用户输入的键的code,然后根据不同的判断显示不同的内容,我有十多个这样的输入框,于是我就想写一个类继承JTextField来实现这个功能,但是,就遇到这个问题了。
      

  5.   

    搞好了,把我的JKeyField.this.setText("A");改成JKeyField.this.setDocument(...)就可以了,谢谢你啊!
      

  6.   

                        final JTextField keyview = new JTextField();
                        keyview.addKeyListener(new KeyAdapter(){
                                @Override public void keyPressed(KeyEvent e){
                                    e.consume();
                                    keyview.setText(KeyEvent.getKeyText(e.getExtendedKeyCode()).toUpperCase());
                                }
                                @Override public void keyReleased(KeyEvent e){
                                    e.consume();
                                }
                                @Override public void keyTyped(KeyEvent e){
                                    e.consume();
                                }
                            });
      

  7.   

    嗯,这样是可以的,假若我现在有10个这样的JTextField ,那么就就需要注册10次,写10次事件。因此我就想利用工厂模型直接写出一个同样的JTextField来,看我代码如下:import java.awt.event.KeyAdapter;
    import java.awt.event.KeyEvent;import javax.swing.JFrame;
    import javax.swing.JTextField;
    import javax.swing.text.AttributeSet;
    import javax.swing.text.BadLocationException;
    import javax.swing.text.DocumentFilter;
    import javax.swing.text.PlainDocument;
    import java.awt.event.KeyEvent;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Set;import model.key.KeysAdapter;public class JKeyField extends JTextField{ private static final long serialVersionUID = 1L;
    private String key = "";
     
    public JKeyField(int size){
    super(size);
    this.addKeyListener(new KeyAdapter(){
    public void keyPressed(final KeyEvent e){
    key = KeysAdapter.disConvert(e.getKeyCode());
    PlainDocument document = new PlainDocument();
    document.setDocumentFilter(new DocumentFilter(){
    @Override 
    public void insertString(DocumentFilter.FilterBypass fb,int offset,String s,AttributeSet as) throws BadLocationException {
    super.insertString(fb,offset,key,as);
    }
    @Override 
    public void replace(DocumentFilter.FilterBypass fb,int offset,int length,String s,AttributeSet as) throws BadLocationException {

    super.replace(fb,offset,length,key,as);
    }
    });

    JKeyField.this.setDocument(document);
    }
    });
    }

    public static void main(String args[]){
    JFrame jf = new JFrame();
    jf.setVisible(true);
    jf.getContentPane().add(new JKeyField(10));
    jf.pack();
    }
    }
    class KeysAdapter {

    public static int INVALID_KEY = -1;
    private static HashMap<String , Integer> keyMap = new HashMap<String , Integer>();
    private static HashMap<Integer , String> backKeyMap = new HashMap<Integer , String>();

    static{
    // 无用键码
    //keyMap.put("", INVALID_KEY);
    // 正常键码
    keyMap.put("0", KeyEvent.VK_0);
    keyMap.put("1", KeyEvent.VK_1);
    keyMap.put("2", KeyEvent.VK_2);
    keyMap.put("3", KeyEvent.VK_3);
    keyMap.put("4", KeyEvent.VK_4);
    keyMap.put("5", KeyEvent.VK_5);
    keyMap.put("6", KeyEvent.VK_6);
    keyMap.put("7", KeyEvent.VK_7);
    keyMap.put("8", KeyEvent.VK_8);
    keyMap.put("9", KeyEvent.VK_9);
    keyMap.put("a", KeyEvent.VK_A);
    keyMap.put("b", KeyEvent.VK_B);
    keyMap.put("c", KeyEvent.VK_C);
    keyMap.put("d", KeyEvent.VK_D);
    keyMap.put("e", KeyEvent.VK_E);
    keyMap.put("f", KeyEvent.VK_F);
    keyMap.put("g", KeyEvent.VK_G);
    keyMap.put("h", KeyEvent.VK_H);
    keyMap.put("i", KeyEvent.VK_I);
    keyMap.put("j", KeyEvent.VK_J);
    keyMap.put("k", KeyEvent.VK_K);
    keyMap.put("l", KeyEvent.VK_L);
    keyMap.put("m", KeyEvent.VK_M);
    keyMap.put("n", KeyEvent.VK_N);
    keyMap.put("o", KeyEvent.VK_O);
    keyMap.put("p", KeyEvent.VK_P);
    keyMap.put("q", KeyEvent.VK_Q);
    keyMap.put("r", KeyEvent.VK_R);
    keyMap.put("s", KeyEvent.VK_S);
    keyMap.put("t", KeyEvent.VK_T);
    keyMap.put("u", KeyEvent.VK_U);
    keyMap.put("v", KeyEvent.VK_V);
    keyMap.put("w", KeyEvent.VK_W);
    keyMap.put("x", KeyEvent.VK_X);
    keyMap.put("y", KeyEvent.VK_Y);
    keyMap.put("z", KeyEvent.VK_Z);
    keyMap.put("-", KeyEvent.VK_MINUS);
    keyMap.put("'", KeyEvent.VK_QUOTE);
    keyMap.put(",", KeyEvent.VK_COMMA);
    keyMap.put(".", KeyEvent.VK_PERIOD);
    keyMap.put("/", KeyEvent.VK_SLASH);
    keyMap.put("\\", KeyEvent.VK_BACK_SLASH);
    keyMap.put(";", KeyEvent.VK_SEMICOLON);
    // 特殊键码
    keyMap.put("F1", KeyEvent.VK_F1);
    keyMap.put("F2", KeyEvent.VK_F2);
    keyMap.put("F3", KeyEvent.VK_F3);
    keyMap.put("F4", KeyEvent.VK_F4);
    keyMap.put("F5", KeyEvent.VK_F5);
    keyMap.put("F6", KeyEvent.VK_F6);
    keyMap.put("F7", KeyEvent.VK_F7);
    keyMap.put("F8", KeyEvent.VK_F8);
    keyMap.put("F9", KeyEvent.VK_F9);
    keyMap.put("F10", KeyEvent.VK_F10);
    keyMap.put("F11", KeyEvent.VK_F11);
    keyMap.put("F12", KeyEvent.VK_F12);
    keyMap.put("Enter", KeyEvent.VK_ENTER);
    keyMap.put("Tab", KeyEvent.VK_TAB);
    keyMap.put("Backspace", KeyEvent.VK_BACK_SPACE);
    keyMap.put("Backspace", KeyEvent.VK_BACK_SPACE);
    keyMap.put("Esc", KeyEvent.VK_ESCAPE);
    keyMap.put(" ", KeyEvent.VK_SPACE);
    keyMap.put("up", KeyEvent.VK_UP);
    keyMap.put("down", KeyEvent.VK_DOWN);
    keyMap.put("left", KeyEvent.VK_LEFT);
    keyMap.put("right", KeyEvent.VK_RIGHT);
    }

    static{
    @SuppressWarnings("rawtypes")
    Set set = keyMap.entrySet();    
    @SuppressWarnings("rawtypes")
    Iterator it = set.iterator();    
    while(it.hasNext()) {    
    @SuppressWarnings("rawtypes")
    Map.Entry entry=(Map.Entry)it.next();    
    backKeyMap.put((Integer)entry.getValue(), (String)entry.getKey());
    }
    } /**
     * 将字符串key转化成KeyEvent中的计算机可识别的键码
     * @param key
     * @return
     */
    public static int convert(String key){
    if(key.equals("")){
    return INVALID_KEY;
    }
    else{
    return keyMap.get(key);
    }
    }

    /**
     * 将计算机可识别的键码转化成字符串key
     * @param key
     * @return
     */
    public static String disConvert(int key){
    if(backKeyMap.containsKey(key)){
    return backKeyMap.get(key);
    }else{
    return "";
    }
    }
      

  8.   

    问题就是当我这样做了之后当输入正常字符时确实没问题,但当我输入回车,退格等特殊字符时就会没反应,也就是说当点击了回车后,文本内容并没有改变,因此不会触发
    @Override 
    public void replace(DocumentFilter.FilterBypass fb,int offset,int length,String s,AttributeSet as) throws BadLocationException {
                        
        super.replace(fb,offset,length,key,as);
    }
      

  9.   

    不好意思最上面的程序有点问题:
    1.将import model.key.KeysAdapter;这一句去掉
    2.在程序的最下面加个"}"
      

  10.   

    写个返回 JTextField得方法即可static public JTextField create(){
        final JTextField input = ...;
        input.addKeyListener(new KeyListener(){
            .... // 类似 #13
        }
        return input;
    }