TableView JAVAFX 2.1中的上下文菜单

3
我想在TableView中添加一个上下文菜单,更具体地说,我想在右键单击表行时显示上下文菜单。
我尝试了这段代码。
 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);

上述代码在JAVAFX 2.0中正常工作,右键单击时我会得到一个上下文菜单。然而当我在JAVAFX 2.1中运行我的代码时,上下文菜单不起作用。
我尝试使用showingProperty()方法获取上下文菜单显示属性,在JAVAFX 2.1中它返回false,在JAVAFX 2.0中返回true。
此外,我还尝试创建自定义的cellfactory类,以下是我的代码(我从官方的JAVAFX TreeView上下文菜单示例中获取):
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();
    }
}

我将这个定制的单元格工厂添加为:
 final Callback<TableColumn, TableCell> cellFactory = 
new Callback<TableColumn, TableCell>() {
    public TableCell call(TableColumn p) {
        return new TextFieldTreeCellImpl();
}

};
col.setCellFactory(cellFactory);

仍然可以在JAVAFX 2.0中正常工作,但在JAVAFX 2.1中无法正常工作。
请帮帮我,我很困扰...

这是JAVAFX 2.1中的一个bug吗? - Deepak
2个回答

3

JavaFX 2.1官方的TreeViewTableView教程都能正常工作。问题是,如果混合使用这些代码示例,当TableColumn的单元格工厂需要TableCell时,就不能返回TreeCell。只需单独按照TableView教程进行操作,并将EditingCell替换为以下具有上下文菜单的内容即可。

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

我的EditingCell类已经有了与您建议的上下文菜单相同的实现。但很奇怪的是,我仍然无法获得所需的效果。 - Deepak
我已经在JavaFX 2.1中测试了我的代码,它按预期工作。请尝试使用尽可能简单的演示代码。 - Uluk Biy

2

即使使用 setContextMenu() 方法,我仍然得不到响应。

然而,这是我解决问题的方法:

我只需注册鼠标事件并在指定位置(在鼠标单击处)显示上下文菜单。

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

如果(me.getButton() == MouseButton.SECONDARY) { table.getContextMenu().show(table, me.getScreenX(), me.getScreenY()); }使用getScreen而不是getScene - Alex

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接