【发布时间】:2021-10-30 13:33:21
【问题描述】:
我在 ComboBox 中遇到“ENTER”键事件传播问题。
我有一个表单(VBox),它在收到“ENTER”键释放事件时提交或执行验证。用户将通过在字段之间切换并点击 UP/DOWN 键在组合框中进行选择来输入详细信息(只是为了最小化鼠标交互)。到目前为止一切正常。
当用户选择 ComboBox 并按下“DOWN”键时,将显示 ComboBox 弹出窗口。用户可以使用 UP/DOWN 键选择选项。选择一个选项后,用户将按“ENTER”键关闭弹出窗口。在这里,我希望“ENTER”事件仅关闭弹出窗口而不提交表单。如果弹出窗口未打开,则 ComboBox 上的“ENTER”键应提交表单。
我尝试通过使用 ComboBox 上的事件来解决此问题。但这没有用。所以两个问题::
谁能告诉我“如何防止 'ENTER' 键事件传播到 VBox,仅当 ComboBox 显示时”?
还有谁能告诉我事件是如何传播到“VBox”处理程序的,尽管在 ComboBox 过滤器/处理程序上消耗了事件?
以下是显示问题的示例:
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListView;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ComboBoxEnterKeyIssue extends Application {
private DateFormat df = new SimpleDateFormat("hh:mm:ss");
@Override
public void start(Stage primaryStage) throws Exception {
TextField textField1 = new TextField();
textField1.setMaxWidth(150);
ComboBox<String> comboBox = new ComboBox<>();
comboBox.setPrefWidth(150);
comboBox.getItems().addAll("Item 1", "Item 2", "Item 3", "Item 4", "Item 5");
comboBox.addEventFilter(KeyEvent.KEY_RELEASED, ke -> {
if (ke.getCode() == KeyCode.DOWN && !comboBox.isShowing()) {
comboBox.show();
ke.consume();
} else if (ke.getCode() == KeyCode.ENTER) {
ke.consume(); // Has no effect !!
}
});
comboBox.addEventHandler(KeyEvent.KEY_RELEASED, ke -> {
if (ke.getCode() == KeyCode.ENTER) {
ke.consume(); // Has no effect !!
}
});
TextField textField2 = new TextField();
textField2.setMaxWidth(150);
ListView<String> output = new ListView<>();
VBox.setVgrow(output, Priority.ALWAYS);
VBox pane = new VBox(textField1, comboBox, textField2, output);
pane.setPadding(new Insets(10));
pane.setSpacing(10);
pane.setOnKeyReleased(ke -> {
if (ke.getCode() == KeyCode.ENTER) {
output.getItems().add(df.format(new Date()) + " :: Enter key released on pane...");
// Form submission/validation is performed here !!
}
});
Scene scene = new Scene(pane, 500, 400);
primaryStage.setScene(scene);
primaryStage.setTitle("ComboBox enter key issue");
primaryStage.show();
}
}
【问题讨论】:
-
我无法在 Windows 10 上使用 Java/JavaFX 16.0.2 重现该问题。虽然对我来说你的 open-dropdown-on-down-arrow-released 不起作用(它似乎只是聚焦下一个文本字段)。
-
我在 JavaFX8 中遇到了这个问题。不幸的是,截至目前我无法升级 JavaFX 版本:(
-
@Slaw 好奇:如果组合没有显示,输入是否会到达窗格?或者我可能误解了要求:如果输入用于关闭弹出窗口,使用并不验证表单,如果在组合不显示时使用输入,是否验证?
-
fx8 远早于对 keyEvent 处理的广泛清理——最糟糕的是安装在 ComboBoxPopupControl 中的任何键上的 eventFilter 会重新触发其父级上收到的键:这样做完全破坏了事件调度(即使在当前的 fx17,仍未完全解决可编辑组合的问题)。令人惊讶的是,即使在当前的 fx 中,解决这个要求(据我所知)也很困难:这里的问题是找到一个合适的条件来判断何时/不使用输入。
-
对于 fx16+:删除 listView 的 inputMap 的输入映射,添加显示的处理程序以将标志切换为真,为组合上的任何键安装键过滤器,在按下和释放之间标志为真(并重置释放标志)..讨厌..