Context Menu in TableView JAVAFX 2.1

java, javafx, javafx-2

Solution

Both official `TreeView` and `TableView` tutorials are working fine with JavaFX 2.1. The problem is, you are mixing these code examples. You cannot return the `TreeCell` when the cell factory of the `TableColumn` needs `TableCell`. Simply follow the TableView tutorial alone only and replace the EditingCell with the following one that has contextMenu:

import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.scene.control.ContextMenu;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TableCell;
import javafx.scene.control.TextField;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;

class EditingCell extends TableCell<Person, String> {

    private TextField textField;
    private ContextMenu addMenu = new ContextMenu();

    public EditingCell() {
        MenuItem addMenuItem = new MenuItem("Print Me");
        addMenu.getItems().add(addMenuItem);
        addMenuItem.setOnAction(new EventHandler() {

            public void handle(Event t) {
                // Do something with current row
                Person curr = getTableView().getItems().get(getIndex());
                System.out.println(curr.getFirstName() + " " + curr.getLastName());
            }
        });
    }

    @Override
    public void startEdit() {
        super.startEdit();

        if (textField == null) {
            createTextField();
        }
        setText(null);
        setGraphic(textField);
        textField.selectAll();
    }

    @Override
    public void cancelEdit() {
        super.cancelEdit();
        setText((String) getItem());
        setGraphic(null);
    }

    @Override
    public void updateItem(String item, boolean empty) {
        super.updateItem(item, empty);

        if (empty) {
            setText(null);
            setGraphic(null);
        } else {
            if (isEditing()) {
                if (textField != null) {
                    textField.setText(getString());
                }
                setText(null);
                setGraphic(textField);
            } else {
                setText(getString());
                setGraphic(null);
                setContextMenu(addMenu);
            }
        }
    }

    private void createTextField() {

        textField = new TextField(getString());
        textField.setMinWidth(this.getWidth() - this.getGraphicTextGap() * 2);
        textField.setOnKeyReleased(new EventHandler<KeyEvent>() {

            @Override
            public void handle(KeyEvent t) {
                if (t.getCode() == KeyCode.ENTER) {
                    commitEdit(textField.getText());
                } else if (t.getCode() == KeyCode.ESCAPE) {
                    cancelEdit();
                }
            }
        });
    }

    private String getString() {
        return getItem() == null ? "" : getItem().toString();
    }
}

Problem

I want to add a context menu to the tableview, more specifically I want to display context menu on table rows on a right click. I tried with this code ``` final EventHandler click = new EventHandler() { public void handle(MouseEvent t) { } @Override public void handle(Event arg0) { } }; final Context menu = new ContextMenu(); MenuItem item = new MenuItem("Add Image"); item.setOnAction(new EventHandler() { public void handle(ActionEvent t) { } @Override public void handle(Event arg0) { //some code here }}); menu.getItems().addAll(item); EditingCell cellFactory = new EditingCell(click,menu); TableColumn col = new TableColumn("column1"); col.setCellFactory(cellFactory); ``` Above code is working correctly in JAVAFX 2.0, and I am getting a context menu on right click, How ever when I run my code with JAVAFX 2.1 Context menu doesnt work. I tried to get context menu's showing property using showingProperty() method and it is returning false in JAVAFX 2.1 and true in JAVAFX 2.0 Further I also tried making my custom cellfactory class and here is my code (I took it from official JAVAFX TreeView context menu example) ``` import javafx.event.Event; import javafx.event.EventHandler; import javafx.scene.control.*; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyEvent; class TextFieldTreeCellImpl extends TableCell<String,String> { private TextField textField; private ContextMenu addMenu = new ContextMenu(); public TextFieldTreeCellImpl() { MenuItem addMenuItem = new MenuItem("Add Employee"); addMenu.getItems().add(addMenuItem); addMenuItem.setOnAction(new EventHandler() { public void handle(Event t) { } }); setContextMenu(addMenu); } @Override public void startEdit() { super.startEdit(); if (textField == null) { createTextField(); } setText(null); setGraphic(textField); textField.selectAll(); } @Override public void cancelEdit() { super.cancelEdit(); setText((String) getItem()); //setGraphic(getTableCell().getGraphic()); } @Override public void updateItem(String item, boolean empty) { super.updateItem(item, empty); if (empty) { setText(null); setGraphic(null); } else { if (isEditing()) { if (textField != null) { textField.setText(getString()); } setText(null); setGraphic(textField); } else { setText(getString()); //setGraphic(getTreeItem().getGraphic()); } } } private void createTextField() { textField = new TextField(getString()); textField.setOnKeyReleased(new EventHandler<KeyEvent>() { @Override public void handle(KeyEvent t) { if (t.getCode() == KeyCode.ENTER) { commitEdit(textField.getText()); } else if (t.getCode() == KeyCode.ESCAPE) { cancelEdit(); } } }); } private String getString() { return getItem() == null ? "" : getItem().toString(); } } ``` and I added this custom cellfactory as: ``` final Callback<TableColumn, TableCell> cellFactory = new Callback<TableColumn, TableCell>() { public TableCell call(TableColumn p) { return new TextFieldTreeCellImpl(); } }; col.setCellFactory(cellFactory); ``` Still it is working fine in JAVAFX 2.0 but not in JAVAFX 2.1 Please help me, I am having a hard time ...

Original source