JTextField的setText方法无法通过KeyListener工作

时间:2011-09-23 06:33:54

标签: java swing jtextfield settext

当我来自KeyListener时,我很困惑为什么JTextField似乎没有通过使用setText(“”)方法来“清除”。它可以在ActionListener中正常工作,但最令人惊讶的是,如果KeyListener方法尝试使用虚拟动作事件(动态创建为简单测试)来调用ActionListener方法,它仍会保留已键入的文本。 / p>

换句话说,当你从命令行运行它时,如果你在字段中键入一个“3”,你会看到setText(“test”)方法不会消除3,如我会期待和渴望,而是将它留在原地。然后,您将在显示屏中看到“test3”。我注意到这一行有评论。单击JButton将正确删除文本。 JButton和JLabel将正确地更改文本。但JTextField不会。如果然后按下按钮,您将看到action事件正确清除了JTextField。现在,如果您切换注释掉的行,您可以看到尝试从KeyTyped方法调用actionPerformed方法!而且,当您在文本字段中键入“3”时,它将不会被删除。我希望setText(“”)方法清除它,它不会。即使keyTyped()方法正在调用与JTextButton相同的actionPerformed()方法,这也是如此。

这里的动机可能会有所帮助。我需要捕获一个特定的热键,它会在键入时清除JTextField,就像按下“清除”按钮一样。这似乎不起作用。

我以前没有用Swing做过那么多,但这很令人费解。

我的SSCCE代码如下:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

class P2 implements KeyListener, ActionListener
{
  JTextField fld;
  JButton btn;
  JLabel  lbl;

  P2()
  {
    JFrame frm = new JFrame("Test");
           fld = new JTextField(10);
    JPanel pnl = new JPanel();
           btn = new JButton("Clear it out");
           lbl = new JLabel("This is a test");

    fld.addKeyListener(this);

    btn.addActionListener(this);

    frm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frm.setSize(400,400);
    frm.setLayout(new FlowLayout() );
    pnl.add(fld);
    pnl.add(btn);
    pnl.add(lbl);
    frm.getContentPane().add(pnl);
    frm.setVisible(true);
  }
  public void keyPressed(KeyEvent ke) {}
  public void keyReleased(KeyEvent ke) {}
  public void keyTyped(KeyEvent ke)
  {
     System.out.println("got a pressed key");

//this is the setText method that ought to wipe clean the field comments:
    this.fld.setText("test");
    this.btn.setText("try again");
    this.lbl.setText("got a presseed key");


//toggle this comment to see the invocation of the action event:
//    this.actionPerformed(new ActionEvent( new Object(), 2, "test")  );

  }
  public void actionPerformed(ActionEvent ae)
  {
     fld.setText("");
     fld.selectAll();
  }
  public static void main(String[] args)
  {
    SwingUtilities.invokeLater
    (
      new Runnable()
      {
        public void run()
        {
          new P2();
        }
      }
    );
  }
}

2 个答案:

答案 0 :(得分:2)

此行为是由于KeyEvent被解雇后字段将处理KeyListener这一事实。您可以通过

消费事件来绕过它
ke.consume();

在方法keyTyped内。

根据您的要求,另一种方法是将清算调用封装在SwingUtilities.invokeLater内,这将在您当前事件之后处理,从而在更新后清除该字段。

答案 1 :(得分:2)

这是一个代码片段,使用键绑定来消除所有按下'a'的文本,实现使用已经在字段的动作映射中注册的动作(注意你仍然需要将代码包装到SwingUtilities.invokeLater中 - 因为霍华德已经建议 - 保证在字段内部处理后处理

    JTextField normal = new JTextField("just a normal field", 10);
    final Action selectAll = normal.getActionMap().get("select-all");
    final Action cut = normal.getActionMap().get("cut-to-clipboard");
    Action combine = new AbstractAction() {

        @Override
        public void actionPerformed(final ActionEvent e) {
            SwingUtilities.invokeLater(new Runnable() {
                @Override
                public void run() {
                    selectAll.actionPerformed(e);
                    cut.actionPerformed(e);

                }
            });
        }

    };
    normal.getActionMap().put("magic-delete-all", combine);
    normal.getInputMap().put(KeyStroke.getKeyStroke("A"), "magic-delete-all");