2016-08-10 106 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; 
}