使用TreeCell的键盘显示上下文菜单 [英] Show context menu using keyboard for TreeCell

查看:64
本文介绍了使用TreeCell的键盘显示上下文菜单的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经尝试了一切.我认为他们犯了个大错误,就是在任何情况下都未引用索引单元格.

I've tried everything. I think they made a big mistake not giving any reference to the indexed cell in anything.

我可以得到菜单,但位置不正确.右键单击即可.

I can get my menu, but not in the right place. Right click is fine.

在TreeView中,我可以使用get KeyReleased,但我不知道将菜单放置在何处.

In my TreeView I can use get KeyReleased but I don't know where to put the menu.

    setOnKeyReleased((KeyEvent t) -> {
        switch (t.getCode()) {
            case CONTEXT_MENU:
                getSelectionModel().getSelectedItem().setGraphic(new Label("hi"));
                //showMenu just calls show on my ContextMenu of my subclass TreeNode
                ((TreeNode)getSelectionModel().getSelectedItem()).showMenu(
                        getSelectionModel().getSelectedItem().getGraphic().getLocalToSceneTransform());
                break;
            }
    });

没有一种布局方法可以给我TreeCell的坐标

None of the layout methods will give me the coords of the TreeCell

推荐答案

根本不可能为给定项目提供对单元格的API访问.并非每个项目都有与之关联的单元格.最重要的是,由单元格表示的项目可能随时更改,因此,即使您可以提供对该单元格的访问权限,API也会非常混乱.

It simply isn't possible to provide API access to the cell for a given item. Not every item has a cell associated with it. On top of that, the item which is represented by a cell may change at any time, so even if you could provide access to the cell, the API would potentially be very confusing.

进行此类操作的基本技巧是创建一个单元工厂,并向该单元注册适当的侦听器.您的案子有些棘手,但有可能.下面的工作来获取代表所选项目的单元格(您可能需要对代码进行一些修改以处理单元格从屏幕上滚动出来的情况).

The basic trick to anything like this is to create a cell factory, and register the appropriate listeners with the cell. Your case is somewhat tricky, but possible. The following works to get the cell representing the selected item (you may want to modify the code somewhat to deal with the case where the cell is scrolled off the screen).

(请注意,由于我的笔记本电脑上没有ContextMenu键,因此我随意使用了Z键.)

(Note that I used the Z key, arbitrarily, as I don't have a ContextMenu key on my laptop.)

import javafx.application.Application;
import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.geometry.Bounds;
import javafx.geometry.Point2D;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TreeCell;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;




public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();

            TreeView<String> treeView = new TreeView<>();
            TreeItem<String> treeRoot = new TreeItem<>("Root");
            for (int i=1; i<=5; i++) {
                TreeItem<String> child = new TreeItem<>("Item "+i);
                child.getChildren().addAll(new TreeItem<>("Item "+i+"A"), new TreeItem<>("Item "+i+"B"));
                treeRoot.getChildren().add(child);
            }
            treeView.setRoot(treeRoot);

            root.setCenter(treeView);

            ObjectProperty<TreeCell<String>> selectedCell = new SimpleObjectProperty<>();
            treeView.setCellFactory(tree -> {
                TreeCell<String> cell = new TreeCell<>();
                cell.textProperty().bind(cell.itemProperty());
                ChangeListener<TreeItem<String>> listener = (obs, oldItem, newItem) -> {
                    TreeItem<String> selectedItem = treeView.getSelectionModel().getSelectedItem();
                    if (selectedItem == null) {
                        selectedCell.set(null);
                    } else {
                        if (selectedItem == cell.getTreeItem()) {
                            selectedCell.set(cell);
                        }
                    }
                };
                cell.treeItemProperty().addListener(listener);
                treeView.getSelectionModel().selectedItemProperty().addListener(listener);
                return cell ;
            });

            ContextMenu contextMenu = new ContextMenu();
            for (int i=1; i<=3; i++) {
                String text = "Choice "+i;
                MenuItem menuItem = new MenuItem(text);
                menuItem.setOnAction(event -> System.out.println(text));
                contextMenu.getItems().add(menuItem);
            }

            treeView.setOnKeyReleased(event -> {
                if (event.getCode() == KeyCode.Z) {
                    if (selectedCell.get() != null) {
                        Node anchor = selectedCell.get();
                                            // figure center of cell in screen coords:
                        Bounds anchorBounds = anchor.getBoundsInParent();
                        double x = anchorBounds.getMinX() + anchorBounds.getWidth() / 2 ;
                        double y = anchorBounds.getMinY() + anchorBounds.getHeight() / 2 ;
                        Point2D screenLoc = anchor.getParent().localToScreen(x, y);
                        contextMenu.show(selectedCell.get(), screenLoc.getX(), screenLoc.getY());
                    }
                }

            });

            Scene scene = new Scene(root,400,400);
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

这篇关于使用TreeCell的键盘显示上下文菜单的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆