Search code examples
javaswingjtreeselectedright-click

jtree right click selects just one node


I have a JTree and I can (ctrl) select multiple nodes. When I right click, I get a popup where I can choose 'refresh'. (there are other questions on this site that explain how to do this)

The problem is, that when I select multiple nodes and I right click, only the node I right clicked gets selected and the others are deselected.

I want to select for example 3 nodes (leafs), right click, choose 'refresh' and still have those 3 nodes selected.

Any advice? Thanks!

example:

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

public class JTreeMultiSelect extends JFrame{

    public JTreeMultiSelect() {
        super("Test");

        JTree myTree = new JTree();
        myTree.getSelectionModel()
                .setSelectionMode(TreeSelectionModel.DISCONTIGUOUS_TREE_SELECTION);
        // add MouseListener to tree
        MouseAdapter ma = new MouseAdapter() {
            private void myPopupEvent(MouseEvent e) {
                int x = e.getX();
                int y = e.getY();
                JTree tree = (JTree)e.getSource();
                TreePath path = tree.getPathForLocation(x, y);
                if (path == null)
                    return;

                tree.setSelectionPath(path);

                DefaultMutableTreeNode rightClickedNode =
                        (DefaultMutableTreeNode)path.getLastPathComponent();

                if(rightClickedNode.isLeaf()){
                    JPopupMenu popup = new JPopupMenu();
                    final JMenuItem refreshMenuItem = new JMenuItem("refresh");
                    refreshMenuItem.addActionListener(new ActionListener(){
                        @Override
                        public void actionPerformed(ActionEvent actionEvent) {
                            System.out.println("refresh!");
                        }
                    });
                    popup.add(refreshMenuItem);
                    popup.show(tree, x, y);
                }
            }
            public void mousePressed(MouseEvent e) {
                if (e.isPopupTrigger()) myPopupEvent(e);
            }
            public void mouseReleased(MouseEvent e) {
                if (e.isPopupTrigger()) myPopupEvent(e);
            }
        };

        myTree.addMouseListener(ma);

        JPanel myPanel = new JPanel();
        myPanel.add(myTree);
        this.add(myPanel);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.pack();
        this.setVisible(true);

    }

    public static void main(String[] args) {
        new JTreeMultiSelect();
    }

}

Solution

  • The following line

    tree.setSelectionPath(path);
    

    resets your tree selection to a single item. You may want to remove this line to get the desired behaviour or even better put it inside a condition to handle the no-selection case also:

    if (tree.isSelectionEmpty()) {
        tree.setSelectionPath(path);
    }