2

我很困惑为什么当 JTextField 来自 KeyListener 时,它似乎不只是通过在其上使用 setText("") 方法来“清除”。它在 ActionListener 中运行良好,但最令人惊讶的是,如果 KeyListener 方法尝试使用虚拟操作事件(作为简单测试动态创建)调用 ActionListener 方法,它仍然会保留键入的文本。

换句话说,当您从命令行运行它时,如果您在字段中键入例如“3”,您将看到 setText("test") 方法不会像我预期的那样清除 3和欲望,而是让它留在原地。然后您将在显示屏中看到“test3”。我已经用评论注意到了这一行。单击 JButton 将正确清除文本。JButton 和 JLabel 将正确更改文本。但 JTextField 不会。如果然后按下按钮,您将看到操作事件正确清除了 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();
        }
      }
    );
  }
}
4

2 回答 2

2

这种行为是由于在您被解雇KeyEvent后将由该字段处理。KeyListener您可以通过使用事件来规避它

ke.consume();

在你的方法里面keyTyped

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

于 2011-09-23T06:37:38.260 回答
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");
于 2011-09-23T07:56:49.960 回答