为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

鸿蒙传说 2023-06-14 14:21:45
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应该显示出来,而无需鼠标进行任何交互。
查看完整描述

1 回答

?
MYYA

TA贡献1868条经验 获得超4个赞

您可以子类化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> {


    /* 

     * May want to provide alternate constructors and static methods similar to

     * the ComboBoxTableCell class (i.e. the superclass).

     */


    private boolean enterPressed;


    public AutoShowComboBoxTableCell(StringConverter<T> converter, ObservableList<T> values) {

        super(converter, values);

        getStyleClass().add("auto-show-combo-box-table-cell");


        // Assumes TableView property is set only once (valid assumption?)

        tableViewProperty().addListener(new InvalidationListener() {

            @Override

            public void invalidated(Observable observable) {

                // Need to know if editing was started by the user pressing

                // the ENTER key (see #startEdit())

                EventHandler<KeyEvent> filter = event -> {

                    if (event.getCode() == KeyCode.ENTER) {

                        enterPressed = event.getEventType() == KeyEvent.KEY_PRESSED;

                    }

                };

                // Possible memory leak? Consider using WeakEventHandler (read docs)

                getTableView().addEventFilter(KeyEvent.KEY_PRESSED, filter);

                getTableView().addEventFilter(KeyEvent.KEY_RELEASED, filter);

                observable.removeListener(this);

            }

        });

    }


    @Override

    public void startEdit() {

        if (isEditing()) return;


        super.startEdit();

        if (isEditing()) {

            if (enterPressed) {

                // Cell was put into edit mode by the user pressing ENTER. This causes

                // problems since *releasing* ENTER while the ComboBox has the focus

                // results in the value being committed; this leads to the current value

                // being committed *immediately* after entering edit mode—not what we want. 

                // To fix that we consume the first ENTER-released event and then let all

                // subsequent events through (by removing the event filter).

                addEventFilter(KeyEvent.KEY_RELEASED, new EventHandler<>() {

                    @Override public void handle(KeyEvent event) {

                        if (event.getCode() == KeyCode.ENTER) {

                            event.consume();

                            removeEventFilter(KeyEvent.KEY_RELEASED, this);

                        }

                    }

                });

            }

            ComboBox<?> comboBox = (ComboBox<?>) getGraphic();

            comboBox.requestFocus(); // Needed to allow releasing ENTER to commit the value

            comboBox.show();

        }

    }


    @Override

    public void cancelEdit() {

        if (isEditing()) {

            super.cancelEdit();

            requestTableViewFocus();

        }

    }


    @Override

    public void commitEdit(T newValue) {

        if (isEditing()) {

            super.commitEdit(newValue);

            requestTableViewFocus();

        }

    }


    // Allows user to keep navigating the table via the keyboard

    private void requestTableViewFocus() {

        TableView<S> tableView = getTableView();

        if (tableView != null) {

            tableView.requestFocus();

        }

    }


}

注意:以上使用了实现细节的知识,图形设置为编辑开始时的事实ComboBox以及导致提交编辑的原因。实施细节可能会更改,恕不另行通知。


查看完整回答
反对 回复 2023-06-14
  • 1 回答
  • 0 关注
  • 133 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信