猿问

如何向 ComboBoxTableCell 添加键盘编辑支持

ComboBoxTableCellComboBox允许在编辑模式下添加一个TableCell。如果comboBox.show()被调用(例如显示弹出窗口),comboBox则按预期按下箭头键和向上箭头键时会做出反应,并在按下回车键后立即结束编辑模式。我只想使用键盘控制编辑。我找不到使用键盘调用“comboBox.show()”的方法。


到现在为止,我尝试使用setOnKeyPressed向ComboBoxTableCell(在通过工厂方法创建期间)或ComboBox(通过使用ComboBoxTableCell.getGraphic())添加回调。调用回调ComboBox.show()以打开弹出窗口,但未调用它们(通过System.out回调中的打印验证)。


actColumn.setCellFactory(

        new Callback<TableColumn<S,Object>, TableCell<S,Object>>() {

    private ObservableList<Object> list=optionList;


    @SuppressWarnings("unchecked")

    @Override

    public TableCell<S, Object> call(TableColumn<S, Object> param) {

        final ComboBoxTableCell<S,Object> cell=

                new ComboBoxTableCell<S,Object>(list);

        cell.setConverter((StringConverter<Object>) converter);

        cell.setOnKeyPressed(event -> {

           cell.startEdit();


            Node node=cell.getGraphic();

            System.out.println(node);

            if(node instanceof ComboBox) {

                System.out.println("Hit Key.");

                final ComboBox<?> box=(ComboBox<?>) node;

                box.show();

            }

        });

除了这段代码很奇怪之外,当在单元格的编辑模式下按下一个键时,处理程序不会被调用(或者至少我没有输出)。


我希望能够选择一个ComboBoxTableCell,按回车键(可能还有一个额外的键),然后内部的弹出窗口ComboBox应该显示出来,而无需鼠标进行任何交互。


鸿蒙传说
浏览 134回答 1
1回答

MYYA

您可以子类化ComboBoxTableCell以添加您想要的行为。这是一个概念验证:import javafx.beans.InvalidationListener;import javafx.beans.Observable;import javafx.collections.ObservableList;import javafx.event.EventHandler;import javafx.scene.control.ComboBox;import javafx.scene.control.TableView;import javafx.scene.control.cell.ComboBoxTableCell;import javafx.scene.input.KeyCode;import javafx.scene.input.KeyEvent;import javafx.util.StringConverter;public class AutoShowComboBoxTableCell<S, T> extends ComboBoxTableCell<S, T> {&nbsp; &nbsp; /*&nbsp;&nbsp; &nbsp; &nbsp;* May want to provide alternate constructors and static methods similar to&nbsp; &nbsp; &nbsp;* the ComboBoxTableCell class (i.e. the superclass).&nbsp; &nbsp; &nbsp;*/&nbsp; &nbsp; private boolean enterPressed;&nbsp; &nbsp; public AutoShowComboBoxTableCell(StringConverter<T> converter, ObservableList<T> values) {&nbsp; &nbsp; &nbsp; &nbsp; super(converter, values);&nbsp; &nbsp; &nbsp; &nbsp; getStyleClass().add("auto-show-combo-box-table-cell");&nbsp; &nbsp; &nbsp; &nbsp; // Assumes TableView property is set only once (valid assumption?)&nbsp; &nbsp; &nbsp; &nbsp; tableViewProperty().addListener(new InvalidationListener() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; public void invalidated(Observable observable) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Need to know if editing was started by the user pressing&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // the ENTER key (see #startEdit())&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; EventHandler<KeyEvent> filter = event -> {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (event.getCode() == KeyCode.ENTER) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; enterPressed = event.getEventType() == KeyEvent.KEY_PRESSED;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; };&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Possible memory leak? Consider using WeakEventHandler (read docs)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; getTableView().addEventFilter(KeyEvent.KEY_PRESSED, filter);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; getTableView().addEventFilter(KeyEvent.KEY_RELEASED, filter);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; observable.removeListener(this);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public void startEdit() {&nbsp; &nbsp; &nbsp; &nbsp; if (isEditing()) return;&nbsp; &nbsp; &nbsp; &nbsp; super.startEdit();&nbsp; &nbsp; &nbsp; &nbsp; if (isEditing()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (enterPressed) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Cell was put into edit mode by the user pressing ENTER. This causes&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // problems since *releasing* ENTER while the ComboBox has the focus&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // results in the value being committed; this leads to the current value&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // being committed *immediately* after entering edit mode—not what we want.&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // To fix that we consume the first ENTER-released event and then let all&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // subsequent events through (by removing the event filter).&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; addEventFilter(KeyEvent.KEY_RELEASED, new EventHandler<>() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; @Override public void handle(KeyEvent event) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (event.getCode() == KeyCode.ENTER) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; event.consume();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; removeEventFilter(KeyEvent.KEY_RELEASED, this);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ComboBox<?> comboBox = (ComboBox<?>) getGraphic();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; comboBox.requestFocus(); // Needed to allow releasing ENTER to commit the value&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; comboBox.show();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public void cancelEdit() {&nbsp; &nbsp; &nbsp; &nbsp; if (isEditing()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super.cancelEdit();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; requestTableViewFocus();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; @Override&nbsp; &nbsp; public void commitEdit(T newValue) {&nbsp; &nbsp; &nbsp; &nbsp; if (isEditing()) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; super.commitEdit(newValue);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; requestTableViewFocus();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; // Allows user to keep navigating the table via the keyboard&nbsp; &nbsp; private void requestTableViewFocus() {&nbsp; &nbsp; &nbsp; &nbsp; TableView<S> tableView = getTableView();&nbsp; &nbsp; &nbsp; &nbsp; if (tableView != null) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; tableView.requestFocus();&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}注意:以上使用了实现细节的知识,图形设置为编辑开始时的事实ComboBox以及导致提交编辑的原因。实施细节可能会更改,恕不另行通知。
随时随地看视频慕课网APP

相关分类

Java
我要回答