Javafx 如何获取当前选定单元格在屏幕上的当前位置?
当用户点击一个特定的键时,我想打开一个上下文菜单。因此,我注册了一个键EventHandler,并成功地打开了contextmenu,但不幸的是,我无法确定contextmenu的正确位置 我想在当前选定的单元格下方打开它: 我无法确定上下文菜单显示的正确位置:Javafx 如何获取当前选定单元格在屏幕上的当前位置?,javafx,position,contextmenu,keylistener,treetableview,Javafx,Position,Contextmenu,Keylistener,Treetableview,当用户点击一个特定的键时,我想打开一个上下文菜单。因此,我注册了一个键EventHandler,并成功地打开了contextmenu,但不幸的是,我无法确定contextmenu的正确位置 我想在当前选定的单元格下方打开它: 我无法确定上下文菜单显示的正确位置: //Showcase Code: treeTableView.setOnKeyPressed( new EventHandler<KeyEvent>() { @Override public void hand
//Showcase Code:
treeTableView.setOnKeyPressed( new EventHandler<KeyEvent>()
{
@Override
public void handle( final KeyEvent keyEvent )
{
final TreeItem<Item> selectedItem = treeTableView.getSelectionModel().getSelectedItem();
if ( selectedItem != null )
{
if ( keyEvent.getCode().equals( KeyCode.INSERT ) )
{
final ContextMenu rowMenu = new ContextMenu();
Menu deleteMenu = new Menu( "Delete" );
final MenuItem deleteItem = new MenuItem( selectedItem.getValue().getName() );
deleteMenu.getItems().add( deleteItem );
rowMenu.getItems().add( deleteMenu );
rowMenu.show( treeTableView.getScene().getWindow() );//How to get X and Y of current selected cell/row?
}
}
}
}
//Showcase代码:
treeTableView.setOnKeyPressed(新的EventHandler()
{
@凌驾
公共无效句柄(最终KeyEvent KeyEvent)
{
final TreeItem selectedItem=treeTableView.getSelectionModel().getSelectedItem();
如果(selectedItem!=null)
{
if(keyEvent.getCode().equals(KeyCode.INSERT))
{
最终上下文菜单行菜单=新上下文菜单();
菜单删除菜单=新菜单(“删除”);
final MenuItem deleteItem=new MenuItem(selectedItem.getValue().getName());
deleteMenu.getItems().add(deleteItem);
rowMenu.getItems().add(deleteMenu);
rowMenu.show(treeTableView.getScene().getWindow());//如何获取当前选定单元格/行的X和Y?
}
}
}
}
有人能帮我从当前选定行/单元格的左下角的TreeTableView确定正确的X和Y位置吗
编辑:
增加了一个小例子:
public class TreeTableViewKeyListenerOnRow 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> item2 = new TreeItem<>( new Item( "Item2" ) );
TreeItem<Item> item3 = new TreeItem<>( new Item( "Item3" ) );
root.getChildren().add( item1 );
item1.getChildren().add( item2 );
root.getChildren().add( item3 );
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<>();
row.setFocusTraversable( true );
row.setOnKeyPressed( new EventHandler<KeyEvent>()
{
@Override
public void handle( final KeyEvent keyEvent )
{
System.out.println( "FIRE!" );//Not Fireing?
final TreeItem<Item> selectedItem = row.getTreeItem();
if ( selectedItem != null )
{
if ( keyEvent.getCode().equals( KeyCode.INSERT ) )
{
final ContextMenu menu = new ContextMenu();
Menu deleteMenu = new Menu( "Delete" );
final MenuItem deleteItem = new MenuItem( selectedItem.getValue().getName() );
deleteMenu.getItems().add( deleteItem );
menu.getItems().add( deleteMenu );
// compute bounds of row in screen:
Bounds boundsInScreen = row.localToScreen( row.getBoundsInLocal() );
double x = boundsInScreen.getMinX();
double y = boundsInScreen.getMinY();
menu.show( treeTableView.getScene().getWindow(), x, y );
}
}
}
} );
return row;
}
} );
BorderPane layout = new BorderPane();
layout.setCenter( treeTableView );
Scene scene = new Scene( layout, 400, 400 );
scene.getStylesheets().add( getClass().getResource( "application.css" ).toExternalForm() );
scene.getStylesheets().add( getClass().getResource( "contextmenu.css" ).toExternalForm() );
primaryStage.setScene( scene );
primaryStage.show();
}
public static void main( final String[] args )
{
launch( args );
}
}
公共类TreeTableViewKeyListenerRow扩展了应用程序
{
@凌驾
公共作废开始(最终阶段初级阶段)
{
TreeItem root=新的TreeItem(新项目(“根”);
TreeItem1=新的TreeItem(新项目(“item1”);
TreeItem2=新的TreeItem(新项目(“item2”);
TreeItem3=新的TreeItem(新项目(“item3”);
root.getChildren().add(item1);
item1.getChildren().add(item2);
root.getChildren().add(item3);
TreeTableColumn=新的TreeTableColumn(“列”);
column.setCellValueFactory(新的TreeItemPropertyValueFactory(“名称”);
最终树视图树视图=新树视图(根);
treeTableView.getColumns().add(列);
treeTableView.setShowRoot(false);
treeTableView.setColumnResizePolicy(treeTableView.CONSTRAINED_RESIZE_策略);
treeTableView.setRowFactory(新回调()
{
@凌驾
公共TreeTableRow调用(最终TreeTableView表视图)
{
final TreeTableRow=新的TreeTableRow();
row.setFocusTraversable(true);
row.setOnKeyPressed(新的EventHandler()
{
@凌驾
公共无效句柄(最终KeyEvent KeyEvent)
{
System.out.println(“着火!”;//不着火?
final TreeItem selectedItem=row.getTreeItem();
如果(selectedItem!=null)
{
if(keyEvent.getCode().equals(KeyCode.INSERT))
{
最终上下文菜单=新上下文菜单();
菜单删除菜单=新菜单(“删除”);
final MenuItem deleteItem=new MenuItem(selectedItem.getValue().getName());
deleteMenu.getItems().add(deleteItem);
menu.getItems().add(deleteMenu);
//计算屏幕中行的边界:
Bounds boundsInScreen=row.localToScreen(row.getBoundsInLocal());
double x=boundsInScreen.getMinX();
double y=boundsInScreen.getMinY();
显示(treeTableView.getScene().getWindow(),x,y);
}
}
}
} );
返回行;
}
} );
BorderPane布局=新建BorderPane();
布局。设置中心(树视图);
场景=新场景(布局,400400);
scene.getStylesheets().add(getClass().getResource(“application.css”).toExternalForm());
scene.getStylesheets().add(getClass().getResource(“contextmenu.css”).toExternalForm());
初级阶段。场景(场景);
primaryStage.show();
}
公共静态void main(最终字符串[]args)
{
发射(args);
}
}
将上下文菜单注册到单个TreeTableRow
s。然后您可以调用row.getBoundsInLocal()
获取行的边界,并调用row.localToScreen(…)
转换到屏幕坐标
treeTableView.setRowFactory(ttv -> {
TreeTableRow<Item> row = new TreeTableRow<>();
row.setOnKeyPressed( new EventHandler<KeyEvent>() {
@Override
public void handle( final KeyEvent keyEvent ) {
final TreeItem<Item> selectedItem = row.getTreeItem();
if ( selectedItem != null ) {
if ( keyEvent.getCode().equals( KeyCode.INSERT ) ) {
final ContextMenu rowMenu = new ContextMenu();
Menu deleteMenu = new Menu( "Delete" );
final MenuItem deleteItem = new MenuItem( selectedItem.getValue().getName() );
deleteMenu.getItems().add( deleteItem );
rowMenu.getItems().add( deleteMenu );
// compute bounds of row in screen:
Bounds boundsInScreen = row.localToScreen(row.getBoundsInLocal());
double x = boundsInScreen.getMinX();
double y = boundsInScreen.getMinY();
rowMenu.show( treeTableView.getScene().getWindow() );//How to get X and Y of current selected cell/row?
}
}
}
}
return row ;
});
treeTableView.setRowFactory(ttv->{
TreeTableRow行=新的TreeTableRow();
row.setOnKeyPressed(新的EventHandler(){
@凌驾
公共无效句柄(最终KeyEvent KeyEvent){
final TreeItem selectedItem=row.getTreeItem();
如果(selectedItem!=null){
if(keyEvent.getCode().equals(KeyCode.INSERT)){
最终上下文菜单行菜单=新上下文菜单();
菜单删除菜单=新菜单(“删除”);
final MenuItem deleteItem=new MenuItem(selectedItem.getValue().getName());
deleteMenu.getItems().add(deleteItem);
rowMenu.getItems().add(deleteMenu);
//计算屏幕中行的边界:
Bounds boundsInScreen=row.localToScreen(row.getBoundsInLocal());
double x=boundsInScreen.getMinX();
double y=boundsInScreen.getMinY();
rowMenu.show(treeTableView.getScene().getWindow());//如何获取当前选定单元格/行的X和Y?
}
}
}
}
返回行;
});
好主意,谢谢。您可能知道,在这样一个简单的展示中实现行的EventHandler时,为什么它不会触发?我没有TreeTableView
可玩,但行可能不可焦点遍历。可以尝试Row.setFocusTraversable(true)
.Ugh.这与,有点像兔子洞有关。不幸的是,这没有起到作用。添加了一个小示例来说明这种行为,如果你想玩的话。