Java JTextField';s setText方法没有';我不能从键盘听者那里工作
我不明白为什么JTextField似乎不只是通过使用setText(“”)方法来“清除”,而这是来自一个KeyListener。它在ActionListener中工作得很好,但最令人惊讶的是,如果KeyListener方法尝试调用ActionListener方法,并使用一个虚拟动作事件(作为一个简单的测试动态创建),它仍然保留键入的文本 换句话说,当您从命令行运行它时,例如,如果您在字段中键入一个“3”,您将看到setText(“test”)方法并没有像我期望的那样删除3,而是将其保留在适当的位置。然后您将在显示屏中看到“test3”。我注意到这一行并发表了评论。单击JButton将正确删除文本。JButton和JLabel将正确更改文本。但JTextField不会。如果然后按下按钮,您将看到操作事件正确地清除了JTextField。现在,如果您切换注释掉的行,您可以看到从KeyTyped方法调用actionPerformed方法的尝试!!!而且,当您在文本字段中键入“3”时,它不会被删除。我希望setText(“”)方法将其清除,但它不会。甚至当keyTyped()方法调用与JTextButton相同的actionPerformed()方法时也是如此 这里的动机可能会有所帮助。我需要捕获一个特定的热键,该热键将在键入JTextField时清除该字段,就像您按下“清除”按钮一样。这似乎不起作用 我以前没有对Swing做过那么多的工作,但这很令人费解 我的SSCCE代码如下:Java JTextField';s setText方法没有';我不能从键盘听者那里工作,java,swing,jtextfield,settext,Java,Swing,Jtextfield,Settext,我不明白为什么JTextField似乎不只是通过使用setText(“”)方法来“清除”,而这是来自一个KeyListener。它在ActionListener中工作得很好,但最令人惊讶的是,如果KeyListener方法尝试调用ActionListener方法,并使用一个虚拟动作事件(作为一个简单的测试动态创建),它仍然保留键入的文本 换句话说,当您从命令行运行它时,例如,如果您在字段中键入一个“3”,您将看到setText(“test”)方法并没有像我期望的那样删除3,而是将其保留在适当的位
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();
}
}
);
}
}
此行为是由于在激发
KeyListener
后,字段将处理KeyEvent
。您可以通过以下方式规避此问题:
ke.consume();
在方法内部键入键
根据您的要求,另一种方法是将清除调用封装在
SwingUtilities.invokeLater
中,该调用将在当前事件后处理,从而在字段更新后清除该字段。下面是一个代码段,它使用键绑定来清除按“a”时的所有文本,实现以使用已在字段的操作映射中注册的操作(注意,您仍然需要将代码包装到SwingUtilities.invokeLater中,正如Howard已经建议的那样,以确保在字段内部处理之后对其进行处理)
不要使用keylisteners,请使用密钥绑定非常简单的修复;ke.consume()消除了这个问题。我不是100%确定这是怎么回事。。。如果在KeyListener尝试重置文本后KeyEvent继续进入JTextField,那么我猜模型会检索存储的文本吗?但是如果密钥事件被使用,那么TextField就不会实际处理该事件。那么模型是如何为未来更新的呢?我不清楚这里的流程。但非常感谢您的修复。我无法让您的代码片段正常工作——我显然需要学习关于键绑定和操作的教程。我想这是做这件事的正确方法,所以我会仔细阅读。但我完全不明白你在另一个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");