質問

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.

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;
            }
    });

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

役に立ちましたか?

解決

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).

(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);
    }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top