2016-04-26 115 views
2

我想讓這個TextField具有建議功能,就像在Lucene中一樣。我搜索了所有的網頁,我只是找到它的組合框。JavaFX TextField自動建議

TextField instNameTxtFld = instNameTxtFld(); 

private TextField instNameTxtFld() { 
    TextField txtFld = new TextField(); 
    txtFld.setPrefSize(600, 75); 
    return txtFld; 
} 

,我不能使用的方法進行組合框的原因是因爲我無法輸入值低於數據庫,如果我用組合框。

private void goNext() { 

    if (nameTxtFld.getText() == null || nameTxtFld.getText().trim().isEmpty() 
      || instNameTxtFld.getText()== null || instNameTxtFld.getText().trim().isEmpty() 
      || addTxtArea.getText() == null || addTxtArea.getText().trim().isEmpty()) { 
     alertDialog.showAndWait(); 
    } else { 
     String satu = idNumTxtFld.getText(); 
     String dua = nameTxtFld.getText(); 
     String tiga = addTxtArea.getText(); 
     String empat = instNameTxtFld.getText(); 
     int delapan = idType.getSelectionModel().getSelectedIndex(); 
     String sembilan = timeStamp.getText(); 
     try { 
      KonekDB.createConnection(); 
      Statement st = KonekDB.conn.createStatement(); 
      String sql = "INSERT INTO privateguest" 
        + "(idNumber, name, address, institution, idType, startTime) " 
        + "VALUES " 
        + "('" + satu + "','" + dua + "','" + tiga + "','" + empat + "','" + delapan + "','" + sembilan + "')"; 

      System.out.println(sql); 
      st.executeUpdate(sql); 

     } catch (SQLException ex) { 

      System.out.println(satu + " " + dua + " " + tiga + " " + empat + " " + delapan + " " + sembilan); 
      System.out.println("SQL Exception (next)"); 
      ex.printStackTrace(); 
     } 
     Frame3Private frame3 = new Frame3Private(english); 
     this.getScene().setRoot(frame3); 
    } 

} 

請幫助我做出最簡單的代碼來做TextField建議/自動完成。

+0

你考慮使用'AutoComplete'從[ControlsFX(http://fxexperience.com/controlsfx/features/)? – Itai

回答

7

這是我的解決方案,基於This

public class AutocompletionlTextField extends TextFieldWithLengthLimit { 
    //Local variables 
    //entries to autocomplete 
    private final SortedSet<String> entries;  
    //popup GUI 
    private ContextMenu entriesPopup; 


    public AutocompletionlTextField() { 
     super(); 
     this.entries = new TreeSet<>(); 
     this.entriesPopup = new ContextMenu(); 

     setListner(); 
    } 


    /** 
    * wrapper for default constructor with setting of "TextFieldWithLengthLimit" LengthLimit 
    * 
    * @param lengthLimit 
    */ 
    public AutocompletionlTextField(int lengthLimit) {   
     this(); 
     super.setLengthLimit(lengthLimit);     
    } 


    /** 
    * "Suggestion" specific listners 
    */ 
    private void setListner() {  
     //Add "suggestions" by changing text 
     textProperty().addListener((observable, oldValue, newValue) -> { 
      String enteredText = getText(); 
      //always hide suggestion if nothing has been entered (only "spacebars" are dissalowed in TextFieldWithLengthLimit) 
      if (enteredText == null || enteredText.isEmpty()) { 
       entriesPopup.hide(); 
      } else { 
       //filter all possible suggestions depends on "Text", case insensitive 
       List<String> filteredEntries = entries.stream() 
         .filter(e -> e.toLowerCase().contains(enteredText.toLowerCase())) 
         .collect(Collectors.toList()); 
       //some suggestions are found 
       if (!filteredEntries.isEmpty()) { 
        //build popup - list of "CustomMenuItem" 
        populatePopup(filteredEntries, enteredText); 
        if (!entriesPopup.isShowing()) { //optional 
         entriesPopup.show(AutocompletionlTextField.this, Side.BOTTOM, 0, 0); //position of popup 
        } 
       //no suggestions -> hide 
       } else { 
        entriesPopup.hide(); 
       } 
      } 
     }); 

     //Hide always by focus-in (optional) and out 
     focusedProperty().addListener((observableValue, oldValue, newValue) -> { 
      entriesPopup.hide(); 
     }); 
    }    


    /** 
    * Populate the entry set with the given search results. Display is limited to 10 entries, for performance. 
    * 
    * @param searchResult The set of matching strings. 
    */ 
    private void populatePopup(List<String> searchResult, String searchReauest) { 
     //List of "suggestions" 
     List<CustomMenuItem> menuItems = new LinkedList<>(); 
     //List size - 10 or founded suggestions count 
     int maxEntries = 10; 
     int count = Math.min(searchResult.size(), maxEntries); 
     //Build list as set of labels 
     for (int i = 0; i < count; i++) { 
      final String result = searchResult.get(i); 
      //label with graphic (text flow) to highlight founded subtext in suggestions 
      Label entryLabel = new Label(); 
      entryLabel.setGraphic(Styles.buildTextFlow(result, searchReauest)); 
      entryLabel.setPrefHeight(10); //don't sure why it's changed with "graphic" 
      CustomMenuItem item = new CustomMenuItem(entryLabel, true); 
      menuItems.add(item); 

      //if any suggestion is select set it into text and close popup 
      item.setOnAction(actionEvent -> { 
       setText(result); 
       positionCaret(result.length()); 
       entriesPopup.hide(); 
      }); 
     } 

     //"Refresh" context menu 
     entriesPopup.getItems().clear(); 
     entriesPopup.getItems().addAll(menuItems); 
    } 


    /** 
    * Get the existing set of autocomplete entries. 
    * 
    * @return The existing autocomplete entries. 
    */ 
    public SortedSet<String> getEntries() { return entries; } 
} 

必須從「文本字段」延伸,而不是「TextFieldWithLengthLimit」,並以「長度限制」刪除構造。

我使用靜態方法來處理樣式。這裏用來在提示結果中「突出顯示」輸入的文本。這裏是methos從這個類代碼:

/** 
* Build TextFlow with selected text. Return "case" dependent. 
* 
* @param text - string with text 
* @param filter - string to select in text 
* @return - TextFlow 
*/ 
public static TextFlow buildTextFlow(String text, String filter) {   
    int filterIndex = text.toLowerCase().indexOf(filter.toLowerCase()); 
    Text textBefore = new Text(text.substring(0, filterIndex)); 
    Text textAfter = new Text(text.substring(filterIndex + filter.length())); 
    Text textFilter = new Text(text.substring(filterIndex, filterIndex + filter.length())); //instead of "filter" to keep all "case sensitive" 
    textFilter.setFill(Color.ORANGE); 
    textFilter.setFont(Font.font("Helvetica", FontWeight.BOLD, 12)); 
    return new TextFlow(textBefore, textFilter, textAfter); 
}  

您可以添加在FXML這個「AutocompletionlTextField」(不要忘了「進口」)或內部構造。要設置使用「條目」消氣「建議」的文章:

AutocompletionlTextField field = new AutocompletionlTextField(); 
field.getEntries().addAll(YOUR_ARRAY_OF_STRINGS); 

好像在我的應用程序: enter image description here

希望它能幫助。

+0

TextFieldWithLengthLimit位於何處? – firephil

+0

這是我自己的組件 - 你注意使用TextField。正如我在評論wrotten:「你必須擴展從」TextField「而不是」TextFieldWithLengthLimit「並刪除構造函數與」長度限制「」。 –

+0

好的謝謝,下次嘗試發佈工作代碼,併發布TextFieldWithLengthLimit代碼也... – firephil

6

您可以使用ControlsFX - >maven

解決方案:

TextFields.bindAutoCompletion(textfield,"text to suggest", "another text to suggest"); 
+1

快速解決方案。但彈出窗口非常慢,我可以在彈出窗口之前鍵入整個單詞。 –