Context Menu in TableView JAVAFX 2.1


Question

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

1
2
7/1/2012 6:57:44 PM

Accepted Answer

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();
    }
}
3
7/1/2012 11:44:06 PM

I am getting no response even when using setContextMenu() method.

However,this is how I solved the problem

I just registered a mouse event and showed the context menu at specified position (at mouse click)

this.setContextMenu(menu);
   this.getContextMenu().setAutoHide(true);

      EventHandler event = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent me) {
    if (me.getButton() == MouseButton.SECONDARY) {
  tableView.getContextMenu().show(tableView, me.getSceneX(), me.getSceneY());
    }
 }
};    
      this.addEventHandler(MouseEvent.MOUSE_CLICKED,event);

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon