上下文菜单打开时如何抑制 TreeTableView 的按键导航事件?
How to supress Key Navigation Events for TreeTableView when ContextMenu is open?
当我将上下文菜单添加到树视图时table,不幸的是,它仍然对上下文菜单未使用的 KeyEvents 做出反应。
例如,单击一个子项 (Item22) 打开其上下文菜单,然后单击左箭头树 table视图会在后台选择子项父项 (Item2),即使上下文菜单已被选中并且在前景并且应该(imo)使用事件,即使它不能处理事件本身。
有没有一种简单的方法可以在上下文菜单打开时使用所有导航事件,这样 table 不会在后台对未使用的 KeyNavigations 做出反应?或者您对如何获得所需的行为有任何其他建议吗?
演示问题的小例子:
public class TreeTableViewContextMenuKeyBehaviourMain extends Application
{
@Override
public void start( final Stage primaryStage )
{
TreeItem<Item> root = new TreeItem<>( new Item( "Root" ) );
TreeItem<Item> item1 = new TreeItem<>( new Item( "Item1" ) );
TreeItem<Item> item11 = new TreeItem<>( new Item( "Item11" ) );
TreeItem<Item> item2 = new TreeItem<>( new Item( "Item2" ) );
TreeItem<Item> item22 = new TreeItem<>( new Item( "Item22" ) );
root.getChildren().add( item1 );
item1.getChildren().add( item11 );
root.getChildren().add( item2 );
item2.getChildren().add( item22 );
TreeTableColumn<Item, String> column = new TreeTableColumn<>( "Column" );
column.setCellValueFactory( new TreeItemPropertyValueFactory<Item, String>( "name" ) );
final TreeTableView<Item> treeTableView = new TreeTableView<>( root );
treeTableView.getColumns().add( column );
treeTableView.setShowRoot( false );
treeTableView.setColumnResizePolicy( TreeTableView.CONSTRAINED_RESIZE_POLICY );
treeTableView.setRowFactory( new Callback<TreeTableView<Item>, TreeTableRow<Item>>()
{
@Override
public TreeTableRow<Item> call( final TreeTableView<Item> tableView )
{
final TreeTableRow<Item> row = new TreeTableRow<>();
final ContextMenu rowMenu = new ContextMenu();
rowMenu.setOnShowing( ( event ) ->
{
System.out.println( "OPEN!" );
//Clear and Rebuild Contextmenu dynamically.
rowMenu.getItems().clear();
Menu deleteMenu = new Menu( "Delete" );
final MenuItem deleteItem = new MenuItem( row.getItem().getName() );
deleteMenu.getItems().add( deleteItem );
rowMenu.getItems().add( deleteMenu );
} );
//If the contextmenu has no childs setOnShowing will not be called, so we need a placeholder for dynamic context menus.
final Menu placeholder = new Menu( "Delete" );
rowMenu.getItems().add( placeholder );
// only display context menu for non-null items:
row.contextMenuProperty().bind(
Bindings.when( Bindings.isNotNull( row.itemProperty() ) ).then( rowMenu )
.otherwise( (ContextMenu) null ) );
return row;
}
} );
BorderPane layout = new BorderPane();
layout.setCenter( treeTableView );
Scene scene = new Scene( layout, 400, 400 );
scene.getStylesheets().add( getClass().getResource( "application.css" ).toExternalForm() );
primaryStage.setScene( scene );
primaryStage.show();
}
public static void main( final String[] args )
{
launch( args );
}
}
public class Item
{
private final StringProperty name = new SimpleStringProperty();
public Item( final String name )
{
this.name.set( name );
}
public String getName()
{
return name.get();
}
public void setName( final String name )
{
this.name.set( name );
}
public StringProperty nameProperty()
{
return name;
}
}
您可以将 EventHandler
添加到您的 ContextMenu
以消耗正在尝试汇集备份场景图的 KeyEvents
。
rowMenu.addEventHandler(KeyEvent.ANY, (KeyEvent t) ->
{
t.consume();
});
当我将上下文菜单添加到树视图时table,不幸的是,它仍然对上下文菜单未使用的 KeyEvents 做出反应。
例如,单击一个子项 (Item22) 打开其上下文菜单,然后单击左箭头树 table视图会在后台选择子项父项 (Item2),即使上下文菜单已被选中并且在前景并且应该(imo)使用事件,即使它不能处理事件本身。
有没有一种简单的方法可以在上下文菜单打开时使用所有导航事件,这样 table 不会在后台对未使用的 KeyNavigations 做出反应?或者您对如何获得所需的行为有任何其他建议吗?
演示问题的小例子:
public class TreeTableViewContextMenuKeyBehaviourMain extends Application
{
@Override
public void start( final Stage primaryStage )
{
TreeItem<Item> root = new TreeItem<>( new Item( "Root" ) );
TreeItem<Item> item1 = new TreeItem<>( new Item( "Item1" ) );
TreeItem<Item> item11 = new TreeItem<>( new Item( "Item11" ) );
TreeItem<Item> item2 = new TreeItem<>( new Item( "Item2" ) );
TreeItem<Item> item22 = new TreeItem<>( new Item( "Item22" ) );
root.getChildren().add( item1 );
item1.getChildren().add( item11 );
root.getChildren().add( item2 );
item2.getChildren().add( item22 );
TreeTableColumn<Item, String> column = new TreeTableColumn<>( "Column" );
column.setCellValueFactory( new TreeItemPropertyValueFactory<Item, String>( "name" ) );
final TreeTableView<Item> treeTableView = new TreeTableView<>( root );
treeTableView.getColumns().add( column );
treeTableView.setShowRoot( false );
treeTableView.setColumnResizePolicy( TreeTableView.CONSTRAINED_RESIZE_POLICY );
treeTableView.setRowFactory( new Callback<TreeTableView<Item>, TreeTableRow<Item>>()
{
@Override
public TreeTableRow<Item> call( final TreeTableView<Item> tableView )
{
final TreeTableRow<Item> row = new TreeTableRow<>();
final ContextMenu rowMenu = new ContextMenu();
rowMenu.setOnShowing( ( event ) ->
{
System.out.println( "OPEN!" );
//Clear and Rebuild Contextmenu dynamically.
rowMenu.getItems().clear();
Menu deleteMenu = new Menu( "Delete" );
final MenuItem deleteItem = new MenuItem( row.getItem().getName() );
deleteMenu.getItems().add( deleteItem );
rowMenu.getItems().add( deleteMenu );
} );
//If the contextmenu has no childs setOnShowing will not be called, so we need a placeholder for dynamic context menus.
final Menu placeholder = new Menu( "Delete" );
rowMenu.getItems().add( placeholder );
// only display context menu for non-null items:
row.contextMenuProperty().bind(
Bindings.when( Bindings.isNotNull( row.itemProperty() ) ).then( rowMenu )
.otherwise( (ContextMenu) null ) );
return row;
}
} );
BorderPane layout = new BorderPane();
layout.setCenter( treeTableView );
Scene scene = new Scene( layout, 400, 400 );
scene.getStylesheets().add( getClass().getResource( "application.css" ).toExternalForm() );
primaryStage.setScene( scene );
primaryStage.show();
}
public static void main( final String[] args )
{
launch( args );
}
}
public class Item
{
private final StringProperty name = new SimpleStringProperty();
public Item( final String name )
{
this.name.set( name );
}
public String getName()
{
return name.get();
}
public void setName( final String name )
{
this.name.set( name );
}
public StringProperty nameProperty()
{
return name;
}
}
您可以将 EventHandler
添加到您的 ContextMenu
以消耗正在尝试汇集备份场景图的 KeyEvents
。
rowMenu.addEventHandler(KeyEvent.ANY, (KeyEvent t) ->
{
t.consume();
});