javafx阻止从默认按钮操作传播的Enter键

时间:2015-08-30 18:54:23

标签: button javafx default

我有一个带有onKeyRelease(...)处理程序的TreeView,它可以监视Enter键。

它会启动一个模式对话窗口,其中包含一个“确定”状态。按钮设置为onAction(...)处理程序的默认值。

当我在对话框中按Enter键时,调用onAction()处理程序,它是否正常工作,并且我明确地关闭()对话框。

Enter键传播回调用的TreeView,并由onKeyRelease()处理程序再次拾取。

问题:如何在调用按钮的onAction后阻止Enter键传播回来?按钮的默认onAction不是关键事件,因此似乎无处可用它。

下面是我正在做的事情的骨架表示。

/**
 * Here is a TreeView Impl framework...
 */
public class TaxonomyEditor extends ... {

    private final KeyReleaseEventHandler keyReleaseEventHandler = new KeyReleaseEventHandler();
    private boolean edited;

    public final void init(Taxonomy taxonomy) {
        ...
        addEventHandler(AppEvent.TREE_ITEM_ADDED_EVENT, new EventHandler<AppEvent>() {
            @Override
            public void handle(AppEvent event) {
                // resync 
                ...
                event.consume();
            }
        });
        addEventHandler(AppEvent.TREE_ITEM_CHANGED_EVENT, new EventHandler<AppEvent>() {
            @Override
            public void handle(AppEvent event) {
                // resync 
                ...
                event.consume();
            }
        });
        addEventHandler(AppEvent.TREE_ITEM_REMOVED_EVENT, new EventHandler<AppEvent>() {
            @Override
            public void handle(AppEvent event) {
                // resync 
                ...
                event.consume();
            }
        });
        getSelectionModel().getSelectedItems().addListener(new ListChangeListener() {

            @Override
            public void onChanged(ListChangeListener.Change c) {
                if (!c.getList().isEmpty()) {
                    // selection tracking
                    // ...
                    // reinstall handler after a change (see bug note in handler)
                    setOnKeyReleased(keyReleaseEventHandler);
                }
            }
        });
    }

    private void newTaxon() {
        logger.debug("add taxon to [{}]", currTaxaTreeItem.getText());
        ...
        boolean edited = new TaxonDefDialog(currTaxaTreeItem, taxonData).edit();
        if (edited) {
            // --------------------------------------------------
            // calls a service to do the heavy lifting
            // --------------------------------------------------
            taxonomyModel.addTaxon(parentTaxaTreeItem, taxonData);
        }
    }

    private void editTaxon() {
        logger.debug("edit taxon [{}]", currTaxaTreeItem.getText());
        ...
        boolean edited = new TaxonDefDialog(parentTaxaTreeItem, newTaxonData).edit();
        if (edited) {
            // --------------------------------------------------
            // another a service call ...
            // --------------------------------------------------
            taxonomyModel.changeTaxon(parentTaxaTreeItem, oldTaxonData, newTaxonData);
        }
    }

    private void deleteTaxon() {
        logger.debug("delete taxon [{}]", currTaxaTreeItem.getText());
        ...
        if (confirmDelete()) {
            // --------------------------------------------------
            // another a service call ...
            // --------------------------------------------------
            taxonomyModel.removeTaxon(parentTaxaTreeItem, (TaxonData) currTaxaTreeItem);
        }
    }

    private class KeyReleaseEventHandler implements EventHandler<KeyEvent> {

        @Override
        public void handle(KeyEvent event) {
            logger.debug("KeyEvent [{}]", event);
            switch (event.getCode()) {
                case ENTER:
                    /*------------------------------------------------------------------*/
                    /* disable the handler before dialog launch to solve an issue where */
                    /* the Enter key from a dialog can not be properly consumed when it */
                    /* is fired from the default button and gets propogated here ...    */
                    /*------------------------------------------------------------------*/
                    setOnKeyReleased(null);
                    event.consume();
                    logger.debug("ENTER Key released on [{}]", currTaxaTreeItem.getText());
                    switch (currTaxaTreeItem.getType()) {
                        case Taxon:
                            editTaxon();
                            break;
                        // other cases...
                    }
                    break;
                case DELETE:
                    event.consume();
                    logger.debug("DELETE Key released on [{}]", currTaxaTreeItem.getText());
                    switch (currTaxaTreeItem.getType()) {
                        case Taxon:
                            deleteTaxon();
                            break;
                        // other cases...
                    }
                    break;
            }
        }
    }
}

/**
 * Here is a dialog - pretty straight forward...
 */
public class TaxonDefDialog extends Stage {

    public TaxonDefDialog(Window owner, TaxaTreeItem parent, TaxaTreeItem taxonData) {
        ...
        init();
    }

    private void init() {

        initModality(Modality.APPLICATION_MODAL);
        initStyle(StageStyle.UTILITY);

        ...

        Button saveBtn = new Button();
        saveBtn.setText("Save");
        saveBtn.setDefaultButton(true);
        saveBtn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                // validate
                ...

                if (valid) {
                    taxonData.setText(term);
                    edited = true;
                    close();
                }
                // --------------------------------------------------
                // Note - this consume does nothing for the ENTER key
                // --------------------------------------------------
                e.consume();
            }
        });

        Button cancelBtn = new Button();
        cancelBtn.setText("Cancel");
        cancelBtn.setCancelButton(true);
        cancelBtn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent e) {
                edited = false;
                close();
            }
        });
    }

    public boolean edit() {
        showAndWait();
        return edited;
    }
}

我无法弄清楚为什么在按下对话框中的默认按钮后返回Enter键。

作为一种解决方法,我将密钥处理程序设置为null并稍后恢复。它有效但却是KLUNKY,而不是应该的样子。

1 个答案:

答案 0 :(得分:0)

Ok, I found the underlying cause...

It seems that the button.setOnAction() handler responds to the KeyPressed event and consumes only that event - leaving the KeyReleased event to propagate.

Changed from setOnKeyReleased(...) to setOnKeyPressed(...) and problem solved!

It's the little things in life that count ;)