2016-08-10 133 views
3

我必須根據用戶輸入創建自動填充ComboBoxJavaFX自動完成ComboBox下拉大小

我的代碼是這樣的:

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); 
    } 
} 

AutoCompleteComboBoxListener從該answer拍攝。

這個自動完成工作正常。我遇到列表大小問題,

運行該應用程序,然後單擊ComboBox下拉列表以查看彈出窗口大小。

  • 在組合框中(這將顯示在彈出的選項ANDRE)類型ANDRE。現在刪除所有字符。(按退格鍵)
  • 現在填充的列表收縮到只有一個項目的大小與滾動條。
  • 再次單擊組合框下拉列表以獲得完整大小的列表。

如何根據內容製作列表大小?

+0

@Reimeus我如何使用sizeScene()方法。 – user3164187

回答

2

這是因爲comboBox.hide();方法未被調用(該下拉列表在show上自動更新)。

可以改善監聽器:

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; 
    } 

} 

此更新將確保該下拉列表將被隱藏和重新顯示的每個搜索String已更改時間。

+0

雖然這可以產生奇怪的視覺效果,但如果彈出窗口只是瞬間消失...... – fabian

+0

是的,我知道。原來的那個已經打算讓我猜這個隱藏顯示機制:'keyPress'上的'comboBox.hide()'。我將搜索如何將下拉列表的大小調整爲沒有「閃爍」的內容。 – DVarga

1

不正是「根據內容列表大小」(這將是awfull如果項目太大,無法BTW屏幕上的數字),但你可以指定顯示的ListView的最小高度使用CSS彈出。

這確保彈出大小決不會變得太小,但它留下一些「空的空間」在ListView的底部,如果項目的數量小:

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