2016-08-10 3 views
3

Ich muss eine automatische Füllung ComboBox basierend auf Benutzereingaben erstellen.JavaFX Autocomplete ComboBox Drop-Down-Größe

Mein Code sieht wie folgt aus:

public class JavaFXApplication1 extends Application { 

    @Override 
    public void start(Stage primaryStage) { 
     ComboBox<String> combo = new ComboBox<>(); 
     ObservableList<String> list = FXCollections.observableArrayList(); 
     list.add("A"); 
     list.add("AND"); 
     list.add("ANDR"); 
     list.add("ANDRE"); 
     list.add("B"); 
     list.add("BP"); 
     list.add("BPO"); 
     combo.setItems(list); 
     new AutoCompleteComboBoxListener(combo); 

     StackPane root = new StackPane(); 
     root.getChildren().add(combo); 

     Scene scene = new Scene(root, 300, 250); 

     primaryStage.setTitle("Hello World!"); 
     primaryStage.setScene(scene); 
     primaryStage.show(); 
    } 

    public static void main(String[] args) { 
     launch(args); 
    } 
} 

die AutoCompleteComboBoxListener von diesem answer genommen wird.

Mit dieser Autocomplete funktioniert gut. Ich sah ein Problem in Listengröße,

Führen Sie die Anwendung und klicken Sie auf die ComboBox Drop-Down, um Popup-Größe zu sehen.

  • Typ ANDRE im Kombinationsfeld (die in Popup-ANDRE Option zeigen) .Jetzt alle Zeichen löschen. (Von Backspace)
  • Nun ist die bevölkerungs Liste schrumpfte auf einen Eintrag Größe mit Bildlaufleiste.
  • Klicken Sie erneut auf das Dropdown-Listenfeld, um die vollständige Liste zu erhalten.

Wie kann ich die Listengröße nach Inhalt machen?

+0

@Reimeus wie kann ich das verwenden sizeToScene() -Methode in diesem Szenario. – user3164187

Antwort

2

Dies ist, weil die comboBox.hide();-Methode nicht aufgerufen wird (die Dropdown-Liste wird automatisch bei Erscheinen aktualisiert).

Sie können die Hörer wie verbessern:

public class AutoCompleteComboBoxListener<T> implements EventHandler<KeyEvent> { 

    private ComboBox<T> comboBox; 
    private ObservableList<T> data; 
    private boolean moveCaretToPos = false; 
    private int caretPos; 

    public AutoCompleteComboBoxListener(final ComboBox<T> comboBox) { 
     this.comboBox = comboBox; 
     data = comboBox.getItems(); 

     this.comboBox.setEditable(true); 
     this.comboBox.setOnKeyReleased(AutoCompleteComboBoxListener.this); 
    } 

    @Override 
    public void handle(KeyEvent event) { 


     if(event.getCode() == KeyCode.UP) { 
      caretPos = -1; 
      moveCaret(comboBox.getEditor().getText().length()); 
      return; 
     } else if(event.getCode() == KeyCode.DOWN) { 
      if(!comboBox.isShowing()) 
       comboBox.show(); 

      caretPos = -1; 
      moveCaret(comboBox.getEditor().getText().length()); 
      return; 
     } 

     if (event.getCode() == KeyCode.RIGHT || event.getCode() == KeyCode.LEFT 
       || event.isControlDown() || event.getCode() == KeyCode.HOME 
       || event.getCode() == KeyCode.END || event.getCode() == KeyCode.TAB) { 
      return; 
     } 

     comboBox.hide(); 

     if(event.getCode() == KeyCode.BACK_SPACE) { 
      moveCaretToPos = true; 
      caretPos = comboBox.getEditor().getCaretPosition(); 
     } else if(event.getCode() == KeyCode.DELETE) { 
      moveCaretToPos = true; 
      caretPos = comboBox.getEditor().getCaretPosition(); 
     } 



     ObservableList<T> list = FXCollections.observableArrayList(); 
     for (int i=0; i<data.size(); i++) { 
      if(data.get(i).toString().toLowerCase().startsWith(
       AutoCompleteComboBoxListener.this.comboBox 
       .getEditor().getText().toLowerCase())) { 
       list.add(data.get(i)); 
      } 
     } 
     String t = comboBox.getEditor().getText(); 

     comboBox.setItems(list); 
     comboBox.getEditor().setText(t); 
     if(!moveCaretToPos) { 
      caretPos = -1; 
     } 
     moveCaret(t.length()); 
     if(!list.isEmpty()) { 
      comboBox.show(); 
     } 
    } 

    private void moveCaret(int textLength) { 
     if(caretPos == -1) 
      comboBox.getEditor().positionCaret(textLength); 
     else 
      comboBox.getEditor().positionCaret(caretPos); 

     moveCaretToPos = false; 
    } 

} 

Dieses Update wird sichergestellt, dass die Dropdown-Liste ausgeblendet und wird jedes Mal, wenn die Suche String wurde geändert wieder gezeigt.

+0

Dies kann jedoch seltsame visuelle Effekte haben, wenn das Popup nur für einen Bruchteil einer Sekunde verschwindet ... – fabian

+0

Ja, ich weiß. Der ursprüngliche war bereits gedacht, um diesen Mechanismus zum Verbergen und Anzeigen zu haben, denke ich: 'comboBox.hide()' auf 'keyPress'. Ich werde suchen, wie könnte ich die Dropdown-Liste Größe auf den Inhalt ohne dieses "Flackern" haben. – DVarga

1

Nicht gerade eine „Listengröße nach Inhalt“ (die awfull wäre, wenn die Anzahl der Elemente zu groß auf dem Bildschirm zu passen BTW), aber Sie die minimale Höhe der ListView in dem gezeigten angeben Popup mit CSS.

Dies stellt sicher, das Popup-Größe nie zu klein wird, aber es lässt einige „leeren Raum“ am unteren Rand des ListView, wenn die Anzahl der Elemente ist klein:

.combo-box .combo-box-popup>.list-view { 
    -fx-min-height: 200; 
}