代码之家  ›  专栏  ›  技术社区  ›  Grumblesaurus

JavaFX组合框-当下拉列表可见时,使控件+A select all-in文本框

  •  1
  • Grumblesaurus  · 技术社区  · 6 年前

    我发现 this example 效果很好。我稍微修改了一下,这样在输入文本时会出现下拉列表。

    TextField ,如果下拉列表可见,则不会选择所有文本。其他东西正在消耗热键。

    以下是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();
        }
    }
    

    以下是我尝试过的一些解决方案。它们都不起作用。问题似乎是JavaFX保留了热键 Ctrl + A

    ( 如果钥匙是 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();
        }
    });
    
    1 回复  |  直到 6 年前
        1
  •  1
  •   kleopatra Aji kattacherry    6 年前

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

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

    这适用于所有版本(8和9+)。 For 9+ the bug 更糟糕的是编辑器中的所有导航都被禁用(也就是说:列表吃左/右)。