2015-11-26 170 views
1

我想写一个使用Swing组件的实时搜索。我正在使用keyListener来跟踪输入。基本上我不希望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); 
} 

在此先感谢

+3

请自己试试看,并告诉我们您的尝试。 –

回答

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(); 
      } 
     }); 
    } 
} 
+0

这正是我所期待的。谢谢! – newbie

0

我猜你想使用与Swing文本分量的KeyListener如一个JTextField(我要猜测,因为你不告诉或显示我们)。如果是这样,那么最好的解决办法是不要。对这些组件使用KeyListener可能会混淆组件的功能。取决于您希望在文本完全注册到文本组件之前还是之后进行侦听,您最好使用DocumentListener或DocumentFilter。

要获得更完美的答案,请发布一个更完整的问题,其中包括您最小的代码示例和有关您的问题的详细信息。

+0

我已经添加了一个片段。基本上,这正是你在第一部分描述的内容。你能否详细说明使用DocumentListener的替代方法? – newbie

+1

阅读Swing教程[如何撰写DocumentFilter]一节(http://docs.oracle.com/javase/tutorial/uiswing/events/documentlistener.html)以获取更多信息和工作示例。基本上,无论何时发生事件,您都会进行搜索。 – camickr

+0

@newbie:也阅读了使用Swing Timers,因为这将是您将用于延迟的内容。 –

1

请勿在密钥或文档事件中等待,它会阻止程序进一步处理。而是保存当前时间或(重新)在事件中启动计时器,然后在其他地方执行您的操作。