JavaFX组合框-生成控件+;下拉列表可见时,将显示“全选”文本框

JavaFX组合框-生成控件+;下拉列表可见时,将显示“全选”文本框,javafx,Javafx,我正在制作一个组合框,它通过键入的文本进行过滤,并在键入文本时显示下拉列表 我发现这很有效。我对其进行了轻微修改,以便在输入文本时显示下拉列表 但是,当我键入几个字母,然后按ctrl+a选择文本字段中的所有文本时,如果下拉列表可见,则不会选择所有文本。还有其他东西在消耗这个热键 以下是MCVE代码: import com.sun.javafx.scene.control.skin.ComboBoxListViewSkin; import javafx.application.Applicati

我正在制作一个组合框,它通过键入的文本进行过滤,并在键入文本时显示下拉列表

我发现这很有效。我对其进行了轻微修改,以便在输入文本时显示下拉列表

但是,当我键入几个字母,然后按ctrl+a选择
文本字段
中的所有文本时,如果下拉列表可见,则不会选择所有文本。还有其他东西在消耗这个热键

以下是MCVE代码:

import com.sun.javafx.scene.control.skin.ComboBoxListViewSkin;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.collections.transformation.FilteredList;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;

public class MCVE extends Application {
    public void start(Stage stage) {
        HBox root = new HBox();

        ComboBox<String> cb = new ComboBox<String>();
        cb.setEditable(true);

        ObservableList<String> items = FXCollections.observableArrayList("One", "Two", "Three", "Four", "Five", "Six",
                "Seven", "Eight", "Nine", "Ten");

        FilteredList<String> filteredItems = new FilteredList<String>(items, p -> true);

        cb.getEditor().textProperty().addListener((obs, oldValue, newValue) -> {
            final TextField editor = cb.getEditor();
            final String selected = cb.getSelectionModel().getSelectedItem();

            Platform.runLater(() -> {

                if ( !editor.getText().isEmpty() ) {
                    cb.show();
                } else {
                    cb.hide();
                }
                if (selected == null || !selected.equals(editor.getText())) {
                    filteredItems.setPredicate(item -> {
                        if (item.toUpperCase().startsWith(newValue.toUpperCase())) {
                            return true;
                        } else {
                            return false;
                        }
                    });
                }
            });
        });

        cb.setItems(filteredItems);

        root.getChildren().add(cb);

        Scene scene = new Scene(root);

        stage.setScene(scene);
        stage.show();

    }

    public static void main(String[] args) {
        launch();
    }
}
如果键是
D
,但不是
A
,则此键也有效

((ComboBoxListViewSkin)cb.getSkin()).getDisplayNode().addEventFilter( KeyEvent.KEY_PRESSED, keyEvent -> {
    if ( keyEvent.isControlDown() && keyEvent.getCode() == KeyCode.A ) {
        cb.getEditor().selectAll();
    }
});
cb.setOnKeyPressed( ( KeyEvent e ) -> {
    if ( e.isControlDown() && e.getCode() == KeyCode.D ) {
        cb.getEditor().selectAll();
    }
});

普通组合的行为相同(没有任何过滤),看起来像一个bug:ctrl-a被下拉列表中的ListView吃掉。要解决这个问题,您可以在列表上安装eventFilter,f.i.在onShown处理程序中-此时安装皮肤:

cb.setOnShown(e -> {
    ComboBoxListViewSkin<?> skin = (ComboBoxListViewSkin<?>) cb.getSkin();
    ListView<?> list = (ListView<?>) skin.getPopupContent();
    list.addEventFilter( KeyEvent.KEY_PRESSED, keyEvent -> {
        if (keyEvent.isControlDown() && keyEvent.getCode() == KeyCode.A ) {
            cb.getEditor().selectAll();
        }
    });
    cb.setOnShown(null);
});
cb.setOnShown(e->{
ComboBoxListViewSkin=(ComboBoxListViewSkin)cb.getSkin();
ListView列表=(ListView)skin.getPopupContent();
list.addEventFilter(按下KeyEvent.KEY,KeyEvent->{
if(keyEvent.isControlDown()&&keyEvent.getCode()==KeyCode.A){
cb.getEditor().selectAll();
}
});
cb.setOnShown(空);
});
这在所有版本(8和9+)中都有效。更糟糕的是,编辑器中的所有导航都被禁用(又名:左/右列表)