首页 > 解决方案 > 在按键上选择 ComboBox 选项。我希望选择模型自动滚动/跳转到所选选项

问题描述

到目前为止我所拥有的:

例如,当我按下 C 键按钮时,会发生这种情况:

以 C 开头的第一项被选中。

selectOptionOnKey (见下文)函数选择了以字母 C 开头的选项

问题:

组合框存储更多可以一次显示的选项。So when the option which is selected is not in the displayed area I want the combo box to scroll down/jump to that option but I don't know how to do that.

通过按字母键选择了一个选项 - 选项不在显示区域中。-这将发生在当前代码中。

通过按字母键选择了一个选项 - 选项不在显示区域中。- 这就是我想要发生的事情!


示例代码:

主要的:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{

        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));

        Scene scene = new Scene(root, 850.0, 650.0);

        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

控制器:

import java.net.URL;
import java.util.ResourceBundle;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.ComboBox;
import javafx.scene.control.SingleSelectionModel;
import javafx.scene.input.KeyCode;

public class SampleController implements Initializable {

    @FXML private ComboBox<String> cb;

    //Entered random options
    private final ObservableList<String> options = FXCollections.observableArrayList(
            "Aab",
            "Aer",
            "Aeq",
            "Arx",
            "Byad",
            "Csca",
            "Csee",
            "Cfefe",
            "Cead",
            "Defea",
            "Dqeqe",
            "Fefaf",
            "Gert",
            "Wqad",
            "Xsad",
            "Zzz"
            );

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        cb.getItems().addAll(options);

        selectOptionOnKey();
    }

    /* When you press a letter key
    *  this method will search for an option(item) that starts with the input letter key 
    *  and it selects the first occurrence in combo box
    */
    public void selectOptionOnKey() {
        cb.setOnKeyPressed(e -> {
            KeyCode keyCode = e.getCode();

            if (keyCode.isLetterKey()) {
                char key = keyCode.getName().charAt(0);

                SingleSelectionModel<String> cbSelectionModel = cb.getSelectionModel();

                cbSelectionModel.select(0);

                for (int i = 0; i < options.size(); i++) {
                    if(cbSelectionModel.getSelectedItem().charAt(0) == key) {
                        // option which starts with the input letter found -> select it
                        cbSelectionModel.select(i);
                        /* Before exiting the function it would be nice if after the selection,
                           the combo box would auto slide/jump to the option which is selected.
                           I don't know how to do that. */
                        return;
                    }
                    else
                        cbSelectionModel.selectNext();
                }   
            }
        });
    }
}

FXML:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.ComboBox?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="SampleController">
   <children>
      <ComboBox fx:id="cb" layoutX="300.0" layoutY="300.0" prefHeight="25.0" prefWidth="173.0" />
   </children>
</AnchorPane>

任何帮助深表感谢。

标签: javafxcombobox

解决方案


作为一般行为,虚拟控件 中的选择不会将选定的索引/项目滚动到可见区域。有点惊讶的是,组合框下拉列表中的列表也不例外 - 本来期望在打开时选择的列表是可见的。

出路是在代码中滚动新选择的项目。这涉及:

  • 获取组合框的皮肤
  • 通过以下方式获取 listView skin.getPopupContent():虽然该方法是公共的,但它的返回类型是一个实现细节..
  • 称呼list.scrollTo(index)

A code snippet, could be called whenever the selection changed, fi in your key handler:

cbSelectionModel.select(i);
ComboBoxListViewSkin<?> skin = (ComboBoxListViewSkin<?>) cb.getSkin();
ListView<?> list = (ListView<?>) skin.getPopupContent();
list.scrollTo(i);

推荐阅读