Я пытаюсь создать стиль автозаполнения TextField , который использует ContextMenu для отображения подсказок под TextField.Мне бы хотелось, чтобы ContextMenu отображалось, когда пользователь нажимает клавишу «Вниз», когда фокус находится на TextField.Это мое текущее решение:
setOnKeyPressed(event -> {
System.out.println("pressed " + event.getCode());
switch (event.getCode()) {
case DOWN:
if(getText().length()>0) {
if (!suggestionMenu.isShowing()) {
suggestionMenu.show(AutoCompleteTextField.this, Side.BOTTOM, 0, 0);
}
suggestionMenu.getSkin().getNode().lookup(".menu-item").requestFocus();
}
break;
}
});
Источник: ContextMenu и программный выбор элемента
Использование этого кодастрелка вниз всегда «выделяет» (синего цвета) первый элемент в списке.Проблема в том, что иногда (для меня это кажется случайным), второе нажатие клавиши со стрелкой не даст никакого ответа в ContextMenu - первый элемент останется выбранным.После этого нажатия он всегда будет работать нормально.
Я бы также предпочел, чтобы нажатие вверх при выделении первого элемента скрывало бы ContextMenu, и это пробел не вызывал бы метод onAction MenuItem s, хотя я не совсем понимаю, как работает фокус / прослушивание события для этого меню.Кажется, что клавиатура имеет два фокуса одновременно - вверх / вниз, пробел и ввод в ContextMenu, а все остальное идет в TextField.
Редактировать: Вот полный пример.При отображении ContextMenu с помощью клавиши со стрелкой вниз иногда это вызывает проблемное поведение, в других случаях нет.
Main.java
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class Main extends Application {
@Override
public void start(Stage stage) throws Exception {
BorderPane pane = new BorderPane();
AutoCompleteTextField actf = new AutoCompleteTextField();
pane.setTop(actf);
stage.setScene(new Scene(pane));
stage.show();
}
}
AutoCompleteTextField.java
import javafx.geometry.Side;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.CustomMenuItem;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
public class AutoCompleteTextField extends TextField {
private ContextMenu suggestionMenu;
public AutoCompleteTextField(){
super();
suggestionMenu = new ContextMenu();
for(int i = 0; i<5; i++) {
CustomMenuItem item = new CustomMenuItem(new Label("Item "+i), true);
item.setOnAction(event -> {
setText("selected");
positionCaret(getText().length());
suggestionMenu.hide();
});
suggestionMenu.getItems().add(item);
}
textProperty().addListener((observable, oldValue, newValue) -> {
if(getText().length()>0){
if (!suggestionMenu.isShowing())
suggestionMenu.show(AutoCompleteTextField.this, Side.BOTTOM, 0, 0);
} else {
suggestionMenu.hide();
}
});
setOnKeyPressed(event -> {
System.out.println("pressed " + event.getCode());
switch (event.getCode()) {
case DOWN:
if(getText().length()>0) {
if (!suggestionMenu.isShowing()) {
suggestionMenu.show(AutoCompleteTextField.this, Side.BOTTOM, 0, 0);
}
suggestionMenu.getSkin().getNode().lookup(".menu-item").requestFocus();
}
break;
}
});
}
}