2
votes

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

}
2
for better help sooner post an SSCCE, short, runable, compilable, about JFrame and JTree only, with added TreeSelectionListener, its selection mode, code where you getSelectedXxx and how to invoke JPopupMenu to be visible - mKorbel
Show us code! It sounds like you are changing the selection on right click, but cannot tell unless I see some code. - ageoff
I added the code. It's in tree.setSelectionPath(path); - Johan Claes
Wouldn't removing the tree.setSelectionPath(path) line solve the problem? - VGR

2 Answers

2
votes

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);
}
2
votes

Here's the working example as promised in the comments:

    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;

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

                    TreePath[] selectionPaths = tree.getSelectionPaths();

                    //check if node was selected
                    boolean isSelected = false;
                    if (selectionPaths != null) {
                        for (TreePath selectionPath : selectionPaths) {
                            if (selectionPath.equals(path)) {
                                isSelected = true;
                            }
                        }
                    }
                    //if clicked node was not selected, select it
                    if(!isSelected){
                        tree.setSelectionPath(path);
                    }

                    //todo : create custom JMenuItem that takes the selectionPaths as parameter
                    //       and do the action for each node (using 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();
        }

    }