我想使用Swing组件编写实时搜索。我正在使用keyListener
来跟踪输入。基本上我不希望每次按下按钮时keyListener
采取动作,而是等待(一段时间)更多的输入输入。每次按下按钮时都会刷新该时间段,并在最终超时时评估输入(例如,在该时间段内没有按下按钮意味着输入完成)。如何将其实现到我的keyListener
?
主要方法的代码段:
static JTextField nameTextField = new JTextField();
public static void main(String args[]) throws Exception {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(nameTextField, BorderLayout.NORTH);
nameTextField.addKeyListener(new KeyListener() {
public void keyTyped(KeyEvent keyEvent) {
//
}
@Override
public void keyPressed(KeyEvent e) {
//
}
@Override
public void keyReleased(KeyEvent e) {
if(waitForMoreInput(50)) {
doSomething(nameTextField.getText());
}
}
}
}
}
);
frame.setSize(250, 100);
frame.setVisible(true);
}
提前致谢
答案 0 :(得分:3)
使用DocumentListener或DocumentFilter要好得多,具体取决于您是否要在文本组件完全注册文本之前或之后进行监听。
DocumentListener将在文本发生变化时进行注册,无论是通过按键,复制和粘贴,还是删除文本。然后,定时器将等待您希望对文本执行任何操作的时间。例如:
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
public class DocListenerFoo extends JPanel {
private JTextField nameTextField = new JTextField(20);
public DocListenerFoo() {
add(new JLabel("Add Text:"));
add(nameTextField);
int timerDelay = 1000; // one second
nameTextField.getDocument().addDocumentListener(new MyDocListener(timerDelay));
}
private class MyDocListener implements DocumentListener {
private Timer docTimer;
private int timerDelay;
public MyDocListener(int timerDelay) {
this.timerDelay = timerDelay;
}
@Override
public void changedUpdate(DocumentEvent e) {
textChangedAction(e);
}
@Override
public void insertUpdate(DocumentEvent e) {
textChangedAction(e);
}
@Override
public void removeUpdate(DocumentEvent e) {
textChangedAction(e);
}
private void textChangedAction(DocumentEvent e) {
Document doc = e.getDocument();
try {
String text = doc.getText(0, doc.getLength());
if (docTimer != null && docTimer.isRunning()) {
docTimer.stop();
}
docTimer = new Timer(timerDelay, new TimerListener(text));
docTimer.setRepeats(false);
docTimer.start();
} catch (BadLocationException e1) {
e1.printStackTrace();
}
}
}
private class TimerListener implements ActionListener {
private String text;
public TimerListener(String text) {
this.text = text;
}
@Override
public void actionPerformed(ActionEvent e) {
// TODO do check on text here
System.out.println("Checking text here: " + text);
}
}
private static void createAndShowGui() {
DocListenerFoo mainPanel = new DocListenerFoo();
JFrame frame = new JFrame("DocListenerFoo");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
答案 1 :(得分:1)
不要在密钥或文档事件中等待,它只会阻止程序进一步处理。而是保存当前时间或(重新)在事件中启动计时器,并在其他地方执行您的操作。
答案 2 :(得分:0)
我猜你正在尝试将KeyListener与Swing文本组件(如JTextField)一起使用(我必须猜测,因为你不告诉或告诉我们)。如果是这样,那么最好的解决方案是不。将KeyListener与这些组件一起使用可能会破坏组件的功能。更好的方法是使用DocumentListener或DocumentFilter,具体取决于您是否要在文本组件完全注册文本之前或之后进行监听。
要获得更完整的答案,请发布更完整的问题,包括最少的代码示例和有关问题的详细信息。