What I have so far:
When I press for example the C key button, this happens:
First item starts with C is selected.
The selectOptionOnKey (see below) function selected the option that starts with letter C.
The problem:
The combo box stores more option that can be displayed at once. 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.
Sample code:
Main:
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);
}
}
Controller:
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>
Any help is much appreciated.
As general behaviour, selection in a virtual control does not scroll the selected index/item into the visible region. Slightly astonished that the list in a comboBox' dropdown is no exception to that rule - would have expected at the one that's selected on opening to be visible.
The way out is to scroll the newly selected item in code. This involves:
skin.getPopupContent()
: while that method is public, its return type is an implementation detail ..list.scrollTo(index)
A code snippet, could be called whenever the selection changed, f.i. in your key handler:
cbSelectionModel.select(i);
ComboBoxListViewSkin<?> skin = (ComboBoxListViewSkin<?>) cb.getSkin();
ListView<?> list = (ListView<?>) skin.getPopupContent();
list.scrollTo(i);