JTree rightclick behaviour like in any Filebrowser
java, jpopupmenu, jtree, swing
Solution
You should try keeping things simple, the following is all you really need:
class RightMouseListener implements MouseListener {
@Override
public void mouseClicked(MouseEvent e) {
if (SwingUtilities.isRightMouseButton(e)) {
int row = tree.getClosestRowForLocation(e.getX(), e.getY());
tree.setSelectionRow(row);
popupMenu.show(e.getComponent(), e.getX(), e.getY());
}
}
...
//other overrides
...
};
This is the bare minimum you need to achieve the functionality you're asking for, you can obviously add more custom functionality as needed.
Problem
I am trying to implement a JTree to represent a database! The Root is the database, which can have several relations. Each relation can have attributes and functional dependencies. Each node (database, relation, attribute and fd) has a different rightclick menu. The first step was to implement the popdown menu in the standard way (first leftclick on a node, then rightclick to show popupmenu). Now I want to change it to the standard behaviour of file-explorers. A rightclick selects the node and shows the correct popupmenu. Currently I am able to rightclick and show a popupmenu, but the menu is incorrect. It is the menu of the previous selected node. Here is an examplepicture of the tree: This here is my class: ``` public class ShowPopupMouseListener extends MouseAdapter { // Refernece: http://goo.gl/plojB private JTree tree; private JPopupMenu dbPopUpMenu; private JPopupMenu relPopUpMenu; private JPopupMenu attrPopUpMenu; private JPopupMenu fdPopUpMenu; private AttrPopupFactory attrPopupFactory; public ShowPopupMouseListener(JTree jTree) { this.tree = jTree; DbPopupFactory dbPopupFactory = new DbPopupFactory(tree); dbPopUpMenu = dbPopupFactory.getDbPopupMenu(); RelPopupFactory relPopupFactory = new RelPopupFactory(tree); relPopUpMenu = relPopupFactory.getRelPopupMenu(); attrPopupFactory = new AttrPopupFactory(tree); attrPopUpMenu = attrPopupFactory.getAttrPopupMenu(); FdPopupFactory fdPopupFactory = new FdPopupFactory(tree); fdPopUpMenu = fdPopupFactory.getFdPopupMenu(); } public void mousePressed(MouseEvent e) { showMenuIfPopupTrigger(e); } public void mouseClicked(MouseEvent e) { showMenuIfPopupTrigger(e); } public void mouseReleased(MouseEvent e) { showMenuIfPopupTrigger(e); } private void showMenuIfPopupTrigger(final MouseEvent e) { if (e.isPopupTrigger()) { setSelectedItemsOnPopupTrigger(e); if (tree.getLastSelectedPathComponent() instanceof DatabaseNode) { addRightClickPopUpMenu(tree, dbPopUpMenu); } else if (tree.getLastSelectedPathComponent() instanceof RelationNode) { addRightClickPopUpMenu(tree, relPopUpMenu); } else if (tree.getLastSelectedPathComponent() instanceof AttributeNode) { attrPopupFactory.updateKeyCheckboxes(); addRightClickPopUpMenu(tree, attrPopUpMenu); } else if (tree.getLastSelectedPathComponent() instanceof FunctionalDependencyNode) { addRightClickPopUpMenu(tree, fdPopUpMenu); } } } private void addRightClickPopUpMenu(Component component, final JPopupMenu popUpMenu) { component.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { if (e.isPopupTrigger()) { showPopUpMenu(e); } } public void mouseReleased(MouseEvent e) { if (e.isPopupTrigger()) { showPopUpMenu(e); } } private void showPopUpMenu(MouseEvent e) { popUpMenu.show(e.getComponent(), e.getX(), e.getY()); } }); } private void setSelectedItemsOnPopupTrigger(MouseEvent e) { TreePath p = tree.getPathForLocation(e.getX(), e.getY()); if (!tree.getSelectionModel().isPathSelected(p)) { tree.getSelectionModel().setSelectionPath(p); } } } ``` And in my tree I initialize it the following way: ``` UIManager.put("PopupMenu.consumeEventOnClose", Boolean.FALSE); tree.getSelectionModel().setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION); tree.addMouseListener(new ShowPopupMouseListener(tree)); ``` Any suggestions why this is not working?