我有一个带有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,而不是应该的样子。
答案 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 ;)