Пример: добавление автозаполнения в JTextField

Автозаполнение может быть очень полезно практически в любом приложении, но его нетривиально реализовать. Итак, вот краткий пример того, как вы могли бы сделать это в Java-фреймворке Swing с JTextField (он также должен работать с JTextArea с небольшими изменениями). Этот пример представляет собой модифицированную версию примера Oracle [http://docs.oracle.com/javase/tutorial/uiswing/components/textarea.html]. Пакет кода com.example.myapp.console; import java.awt.event.ActionEvent; import java.util.Collections; я

Автозаполнение может быть очень полезно практически в любом приложении, но его нетривиально реализовать. Итак, вот краткий пример того, как вы могли бы сделать это в Java-фреймворке Swing с JTextField (он также должен работать с JTextArea с небольшими изменениями). Этот пример представляет собой модифицированную версию примера Oracle .

Код

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
     package com.example.myapp.console; 
     
     import java.awt.event.ActionEvent; 
     import java.util.Collections; 
     import java.util.List; 
     
     import javax.swing.AbstractAction; 
     import javax.swing.JTextField; 
     import javax.swing.SwingUtilities; 
     import javax.swing.event.DocumentEvent; 
     import javax.swing.event.DocumentListener; 
     import javax.swing.text.BadLocationException; 
     
     public class Autocomplete implements DocumentListener { 
     
      private static enum Mode { 
        INSERT, 
        COMPLETION 
      }; 
      
      private JTextField textField; 
      private final List<String> keywords; 
      private Mode mode = Mode.INSERT; 
      
      public Autocomplete(JTextField textField, List<String> keywords) { 
        this.textField = textField; 
        this.keywords = keywords; 
        Collections.sort(keywords); 
      } 
      
      @Override 
      public void changedUpdate(DocumentEvent ev) { } 
      
      @Override 
      public void removeUpdate(DocumentEvent ev) { } 
      
      @Override 
      public void insertUpdate(DocumentEvent ev) { 
        if (ev.getLength() != 1) 
          return; 
            
        int pos = ev.getOffset(); 
        String content = null; 
        try { 
          content = textField.getText(0, pos + 1); 
        } catch (BadLocationException e) { 
          e.printStackTrace(); 
        } 
      
        // Find where the word starts 
        int w; 
        for (w = pos; w >= 0; w--) { 
          if (!Character.isLetter(content.charAt(w))) { 
            break; 
          } 
        } 
      
        // Too few chars 
        if (pos - w < 2) 
          return; 
            
        String prefix = content.substring(w + 1).toLowerCase(); 
        int n = Collections.binarySearch(keywords, prefix); 
        if (n < 0 && -n <= keywords.size()) { 
          String match = keywords.get(-n - 1); 
          if (match.startsWith(prefix)) { 
            // A completion is found 
            String completion = match.substring(pos - w); 
            // We cannot modify Document from within notification, 
            // so we submit a task that does the change later 
            SwingUtilities.invokeLater(new CompletionTask(completion, pos + 1)); 
          } 
        } else { 
          // Nothing found 
          mode = Mode.INSERT; 
        } 
      } 
      
      public class CommitAction extends AbstractAction { 
        /** 
        * 
        */ 
        private static final long serialVersionUID = 5794543109646743416L; 
      
        @Override 
        public void actionPerformed(ActionEvent ev) { 
          if (mode == Mode.COMPLETION) { 
            int pos = textField.getSelectionEnd(); 
            StringBuffer sb = new StringBuffer(textField.getText()); 
            sb.insert(pos, " "); 
            textField.setText(sb.toString()); 
            textField.setCaretPosition(pos + 1); 
            mode = Mode.INSERT; 
            } else { 
            textField.replaceSelection("\t"); 
          } 
        } 
      } 
  
      private class CompletionTask implements Runnable { 
        private String completion; 
        private int position; 
  
        CompletionTask(String completion, int position) { 
          this.completion = completion; 
          this.position = position; 
        } 
  
        public void run() { 
          StringBuffer sb = new StringBuffer(textField.getText()); 
          sb.insert(position, completion); 
          textField.setText(sb.toString()); 
          textField.setCaretPosition(position + completion.length()); 
          textField.moveCaretPosition(position); 
          mode = Mode.COMPLETION; 
        } 
      } 
     } 

Использование кода

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
     private static final String COMMIT_ACTION = "commit"; 
     JTextField mainTextField = new JTextField(); 
     
     // Without this, cursor always leaves text field 
     mainTextField.setFocusTraversalKeysEnabled(false); 
     ... 
     // Our words to complete 
     keywords = new ArrayList<String>(5); 
     keywords.add("example"); 
     keywords.add("autocomplete"); 
     keywords.add("stackabuse"); 
     keywords.add("java"); 
     Autocomplete autoComplete = new Autocomplete(mainTextField, keywords); 
     mainTextField.getDocument().addDocumentListener(autoComplete); 
     
     // Maps the tab key to the commit action, which finishes the autocomplete 
     // when given a suggestion 
     mainTextField.getInputMap().put(KeyStroke.getKeyStroke("TAB"), COMMIT_ACTION); 
     mainTextField.getActionMap().put(COMMIT_ACTION, autoComplete.new CommitAction()); 

Если вы хотите, чтобы список ключевых слов в вашем приложении со временем менялся (например, если вы автоматически заполняете имена друзей онлайн в приложении чата), то все, что вам нужно сделать, это добавить метод установки в Autocomplete for List<String> keywords и обновите список ключевых слов нужным Strings

comments powered by Disqus