JavaFX中的自動完成組合框


Answers

我找到了適合我的解決方案:

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

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

    public AutoCompleteComboBoxListener(final ComboBox comboBox) {
        this.comboBox = comboBox;
        sb = new StringBuilder();
        data = comboBox.getItems();

        this.comboBox.setEditable(true);
        this.comboBox.setOnKeyPressed(new EventHandler<KeyEvent>() {

            @Override
            public void handle(KeyEvent t) {
                comboBox.hide();
            }
        });
        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;
        } else if(event.getCode() == KeyCode.BACK_SPACE) {
            moveCaretToPos = true;
            caretPos = comboBox.getEditor().getCaretPosition();
        } else if(event.getCode() == KeyCode.DELETE) {
            moveCaretToPos = true;
            caretPos = comboBox.getEditor().getCaretPosition();
        }

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

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

}

你可以調用它

new AutoCompleteComboBoxListener<>(comboBox);

它是基於 ,我定制它以適應我的需求。

隨意使用它,如果有人能改善它,告訴我。

Question

我正在尋找一種將自動完成功能添加到JavaFX ComboBox 。 在搜索了很多之後,現在是時候在這裡問問了。

AutoFillBox是已知的,但不是我正在搜索的。 我想要的是一個可編輯的組合框,而輸入列表時應該過濾。 但我也想打開列表,而不打字,看到整個項目。

任何想法?




這裡是一個簡單的

public class AutoShowComboBoxHelper {
    public AutoShowComboBoxHelper(final ComboBox<String> comboBox, final Callback<String, String> textBuilder) {
        final ObservableList<String> items = FXCollections.observableArrayList(comboBox.getItems());

        comboBox.getEditor().textProperty().addListener((ov, o, n) -> {
            if (n.equals(comboBox.getSelectionModel().getSelectedItem())) {
                return;
            }

            comboBox.hide();
            final FilteredList<String> filtered = items.filtered(s -> textBuilder.call(s).toLowerCase().contains(n.toLowerCase()));
            if (filtered.isEmpty()) {
                comboBox.getItems().setAll(items);
            } else {
                comboBox.getItems().setAll(filtered);
                comboBox.show();
            }
        });
    }
}

和一種使用它的方法:

new AutoShowComboBoxHelper(combo, item -> buildTextToCompare(item));

為了簡單起見,我在這段代碼中使用了String :: contains,為了獲得更好的性能,使用org.apache.commons.lang3.StringUtils :: containsIgnoreCase




我環顧四周嘗試一些東西。 這看起來不錯:

public void handle( KeyEvent event ) {
        if( event.getCode() == KeyCode.BACK_SPACE)
            s = s.substring( 0, s.length() - 1 );
        else s += event.getText();
        for( String item: items ) {
            if( item.startsWith( s ) ) sm.select( item );
        }
    }

一個用於選擇與匹配開始charakter的項目的關鍵句柄。

我希望這對你有所幫助




不知道這是否仍然相關,但是談到了這個話題。 嘗試了上面的方法,為自己做了一個變化。 但到目前為止,這個fxapps博客的結果是最好看的(但不得不做一些修改,因為我的項目列表不是靜態的,但仍然...)。 希望這會成為下一個會發現這個話題有趣的人。




Related